Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Help coding boot up...
 
Share:
Notifications
Clear all

[Solved] Help coding boot up welcome screen

5 Posts
2 Users
0 Reactions
2,470 Views
(@alj86)
Active Member
Joined: 4 years ago
Posts: 3
Topic starter  

Hello,

First post in your forums!

I was working on a project and wished to implement a boot up/welcome screen with simple fonts for a couple of seconds before the main program kicks in.

But so far I have failed to do so with my limited knowledge in C++.

The code is not mine, I just added the welcome screen part underneath void setup() with u8g2 library.

All I'm getting is a blank screen with the amount of delay() I'm specifying, so surely I'm doing it wrong or missing something.

Your help is greatly appreciated!

This is the full code:

so/*
ssm-oled - Solar Seeing Scintillation Monitor Arduino
Copyright (C) 2017 Paul De Backer

Based on the original design by E. J. Seykora
and inspired by the code modifications done by Ian Lauwerys and Filip Szczerek 

This file is part of ssMon.

ssMon is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ssMon is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ssMon.  If not, see < http://www.gnu.org/licenses/>. 
*/


// Following defines influence the compile:
//  - EMULATOR: defines the build for a real device or emulator
//  - OLED: defines if a display is attached (currently ONE_WIRE OLED Display
//#define EMULATOR 
#define OLED

#include <Arduino.h>

#ifdef OLED
// see  https://github.com/olikraus/u8g2 
  #include <U8g2lib.h>
#endif

#ifdef OLED
  #include <SPI.h>
  #include <Wire.h>
#endif

#define ADC1 A0			// ** Arduino analog input pin, reads intensity from LMC6484 pin 14
#define ADC2 A1			// ** Arduino analog input pin, reads variation from LMC6484 pin 8

#define DISCRIMINATE_LOW     0.5	// ** Set variation value to zero if intensity is too low, default 0.5
#define DISCRIMINATE_HIGH   10.0	// ** Set variation value to zero if variation is too high, default 10

#define INTENSITY_OFFSET  0.0	// ** Intensity dc offset, default 0.0, should not need to change if resistor on U1 can be adjusted to keep value between 0.5V and 1.0V
#define VARIATION_OFFSET -0.05	// ** Variation dc offset, default -0.5, may need to adjust to keep variation output the the range > 0.0 and < 10.0

#define MOVING_AVERAGE_PTS 60	// ** Number of points to use for calculating the variation moving average, default 20

#define METER_POS 88
#define METER_BOTTOM 8
#define METER_MIN_DISPLAY 3
#define TEXT_BOTTOM METER_BOTTOM + 12
#define METER_WIDTH 4
#define METER_HEIGHT 1
static unsigned char graymeter_bits[] = { 0xAA };
static unsigned char meter_bits[] = { 0xFE };

#define SUN_HEIGHT 7
#define SUN_WIDTH 7
static unsigned char Sun[] = { 0x08, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08 };

#define MAX_BARS 7
#define MAX_POINTS 116

long timer_millisec = 0;

#ifdef OLED
  U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);
#endif

// Returns a formatted string created with snprintf()
constexpr int MAX_PRINTF_LENGTH = 64;
#define FLOAT_ARGS(value, fractWeight)  (int)(value), (int)((value) * (fractWeight)) % (fractWeight)

char *FormatStr(const char *format, ...)
{
	static char buf[MAX_PRINTF_LENGTH + 1];

	va_list args;

	va_start(args, format);
	vsnprintf(buf, MAX_PRINTF_LENGTH + 1, format, args);
	va_end(args);

	return buf;
}

#ifdef OLED
  void drawScreen(float Input, float Seeing, float movingAverage)
  {
  	static int curPos = 0;
  	static int graph[MAX_POINTS];
  	static int graphavg[MAX_POINTS];
  	int meterInput = int (round(Input * 10));
  	float work = (Seeing * 100);
  	if (work > 350)
  		work = 350;
  	int graphSeeing = int (round(work / 10));
  	work = (movingAverage * 100);
  	if (work > 300)
  		work = 300;
  	int graphmAverage = int (round(work / 10));
  
  	if (curPos >= MAX_POINTS) {	// Shift array
  		for (int s = 1; s < MAX_POINTS; s++) {
  			graphavg[s - 1] = graphavg[s];
  			graph[s - 1] = graph[s];
  		}
  		curPos = MAX_POINTS - 1;
  	}
  	graph[curPos] = graphSeeing;
  	graphavg[curPos] = graphmAverage;
  	curPos++;
  
  	u8g2.firstPage();
  	do {
  
  u8g2.setFont(u8g2_font_profont10_tr);
  u8g2.drawStr(1, 5 SolarSeeing:)
  		int i = 0;
  		int y = 0;
  		u8g2.setFontMode(1);
  		u8g2.setDrawColor(1);
  		u8g2.setFontPosCenter();
  		while (i < MAX_BARS) {
  			y = MAX_BARS;
  			while (y >= 0) {
  				if (meterInput > i + METER_MIN_DISPLAY)
  					if (i - y >= 0) {
  						u8g2.drawXBM(METER_POS +
  							     (i * METER_WIDTH),
  							     METER_BOTTOM - y,
  							     METER_WIDTH,
  							     METER_HEIGHT,
  							     meter_bits);
  					}
  				y--;
  			}
  			u8g2.drawXBM(METER_POS + (i * METER_WIDTH),
  				     METER_BOTTOM + 1, METER_WIDTH,
  				     METER_HEIGHT, graymeter_bits);
  			i++;
  		}
  		if (meterInput >= 6)
  			u8g2.drawXBM(METER_POS - SUN_WIDTH - 4,
  				     METER_BOTTOM - 5, SUN_WIDTH, SUN_HEIGHT,
  				     Sun);
  		if (Input > 1.0)
  			u8g2.drawStr(METER_POS - SUN_WIDTH - 10, METER_BOTTOM,
  				     "H");
  
  		u8g2.drawHLine(128 - MAX_POINTS - 4, 63, MAX_POINTS + 4);
  		u8g2.drawHLine(128 - MAX_POINTS - 4, 63 - 10, MAX_POINTS + 4);
  		u8g2.drawHLine(128 - MAX_POINTS - 4, 63 - 20, MAX_POINTS + 4);
  		u8g2.drawHLine(128 - MAX_POINTS - 4, 63 - 30, MAX_POINTS + 4);
  
  		u8g2.drawStr(METER_POS, TEXT_BOTTOM,
  			     FormatStr("%01d" "." "%02d V",
  				       FLOAT_ARGS(Input, 100)));
  		u8g2.setFont(u8g2_font_profont22_tr);
  		u8g2.drawStr(0, TEXT_BOTTOM,
  			     FormatStr("%01d" "." "%02d\"",
  				       FLOAT_ARGS(Seeing, 100)));
  		u8g2.drawVLine(128 - MAX_POINTS - 3, 29, 35);
  		for (i = 0; i < MAX_POINTS; i++) {
  			u8g2.drawVLine(128 - MAX_POINTS + i, 63 - graph[i],
  				       graph[i]);
  			if (graphavg[i] > 0) {
  				u8g2.setDrawColor(2);
  				u8g2.drawVLine(128 - MAX_POINTS + i,
  					       63 - graphavg[i] - 1, 2);
  				u8g2.setDrawColor(1);
  			}
  		}
  
  		u8g2.setFont(u8g2_font_profont10_tr);
  
  		u8g2.drawStr(0, 63 - 30, "3");
  		u8g2.drawStr(0, 63 - 20, "2");
  		u8g2.drawStr(0, 63 - 10, "1");
  	}
  	while (u8g2.nextPage());
  
  }

#endif

int sampleCount = 0;

float variationValue,
    intensityValue,
    variationOffset = VARIATION_OFFSET, intensityOffset = INTENSITY_OFFSET;
    
float discriminateLow = DISCRIMINATE_LOW,
    discriminateHigh = DISCRIMINATE_HIGH;

int movingAveragePts = MOVING_AVERAGE_PTS, movingAverageCount = 0;

float movingAverageAcc = 0, movingAverage = 0;
  
void setup(void)
{
	Serial.begin(115200);
 
#ifdef OLED
	u8g2.begin();
  u8g2.setFont(u8g2_font_bubble_tr);  // choose a suitable font
  u8g2.drawStr(20, 30, "SSSM");  // write something to the internal memory
  u8g2.setFont(u8g2_font_profont10_tr);
  u8g2.drawStr(20, 40, "by Paul De Backer");
  u8g2.sendBuffer();          // transfer internal memory to the display
  u8g2.clearBuffer();
#endif
	randomSeed(analogRead(0));
}

int i = 0;

void loop(void)
{
variationValue = intensityValue = 0;  // Reset variation and intensity samples

#ifdef EMULATOR
    intensityValue =  float((random(60, 65) / 100.));
  	const float MIN_RAND = 0.5, MAX_RAND = 4.0;
  	const float range = MAX_RAND - MIN_RAND;
  	variationValue = float((random(10, 400) / 100.));
  	    (range * ((((float)rand()) / (float)RAND_MAX)) + MIN_RAND);
    delay (800);

#else
for (timer_millisec = millis(), sampleCount = 0; millis() - timer_millisec <= 1000; sampleCount++)
  {
		intensityValue += ((analogRead(ADC1) - 511.) * 2.5 / 511.);	// Accumulate average solar intensity sample
		variationValue += (sq((analogRead(ADC2) - 511.) * 2.5 / 511.));	// Accumulate RMS variation sample
	}

	intensityValue = intensityValue / sampleCount + intensityOffset;	// Find average solar intensity, +/– dc offset
	variationValue = (4.46 * sqrt(variationValue / sampleCount) + variationOffset) / intensityValue;	// Find RMS variation, +/– small dc offset, normalised for intensity
#endif 

  if (intensityValue < discriminateLow
      || variationValue > discriminateHigh || variationValue < 0) {
    variationValue = 0; // Discriminate for clouds by setting variation value to zero
    // movingAverage = 0;
    if (intensityValue < 0)
      intensityValue = 0;
  }
  
#ifdef OLED
	movingAverageAcc = movingAverageAcc + variationValue;	// Add the current variation to the moving average accumulator
	if (movingAverageCount = movingAveragePts) {
		movingAverageAcc = movingAverageAcc - movingAverage;	// Deduct the previous moving average from the accumulator
		movingAverage = movingAverageAcc / movingAveragePts;	// Calculate the new moving average
	} else {
		movingAverageCount++;	// Not enough data points yet, so keep accumulating
	}

  drawScreen(intensityValue, variationValue, movingAverage);
  
#endif
  Serial.print("A0: ");
  Serial.println(intensityValue,2);
  Serial.print("A1: ");
  Serial.println(variationValue,2);
}

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2805
 

Hi alj86,

Welcome to the forum!
That's quite some code you have there.

I assume this is the welcome message you're looking at, right?

void setup(void)
{
	Serial.begin(115200);
 
#ifdef OLED
	u8g2.begin();
  u8g2.setFont(u8g2_font_bubble_tr);  // choose a suitable font
  u8g2.drawStr(20, 30, "SSSM");  // write something to the internal memory
  u8g2.setFont(u8g2_font_profont10_tr);
  u8g2.drawStr(20, 40, "by Paul De Backer");
  u8g2.sendBuffer();          // transfer internal memory to the display
  u8g2.clearBuffer();
#endif
	randomSeed(analogRead(0));
}

 

I have no experience with u8g2, so here a first stab at it (assuming you tested the display already with u8g2 and had it working before adding all the other code);

I've moved the clearBuffer to right after the begin statement (based on the u8g2 Wiki example here).
I've also commented out the second line, just to make sure it did not interfere (we can get that to work afterwards).

void setup(void)
{
	Serial.begin(115200);
 
#ifdef OLED
	u8g2.begin();
        u8g2.clearBuffer();
        u8g2.setFont(u8g2_font_bubble_tr);  // choose a suitable font
        u8g2.drawStr(20, 30, "SSSM");  // write something to the internal memory
 //       u8g2.setFont(u8g2_font_profont10_tr);
 //       u8g2.drawStr(20, 40, "by Paul De Backer");
        u8g2.sendBuffer();          // transfer internal memory to the display
#endif
	randomSeed(analogRead(0));
        delay(5000); // just for testing 
}

 

Again: I'm assuming you have tested one or two of the relatively simple examples from the u8g2 library - just to make sure the display works properly.

Does the code work?

 


   
ReplyQuote
(@alj86)
Active Member
Joined: 4 years ago
Posts: 3
Topic starter  
Posted by: @hans

Hi alj86,

Welcome to the forum!
That's quite some code you have there.

I assume this is the welcome message you're looking at, right?

void setup(void)
{
	Serial.begin(115200);
 
#ifdef OLED
	u8g2.begin();
  u8g2.setFont(u8g2_font_bubble_tr);  // choose a suitable font
  u8g2.drawStr(20, 30, "SSSM");  // write something to the internal memory
  u8g2.setFont(u8g2_font_profont10_tr);
  u8g2.drawStr(20, 40, "by Paul De Backer");
  u8g2.sendBuffer();          // transfer internal memory to the display
  u8g2.clearBuffer();
#endif
	randomSeed(analogRead(0));
}

 

I have no experience with u8g2, so here a first stab at it (assuming you tested the display already with u8g2 and had it working before adding all the other code);

I've moved the clearBuffer to right after the begin statement (based on the u8g2 Wiki example here).
I've also commented out the second line, just to make sure it did not interfere (we can get that to work afterwards).

void setup(void)
{
	Serial.begin(115200);
 
#ifdef OLED
	u8g2.begin();
        u8g2.clearBuffer();
        u8g2.setFont(u8g2_font_bubble_tr);  // choose a suitable font
        u8g2.drawStr(20, 30, "SSSM");  // write something to the internal memory
 //       u8g2.setFont(u8g2_font_profont10_tr);
 //       u8g2.drawStr(20, 40, "by Paul De Backer");
        u8g2.sendBuffer();          // transfer internal memory to the display
#endif
	randomSeed(analogRead(0));
        delay(5000); // just for testing 
}

 

Again: I'm assuming you have tested one or two of the relatively simple examples from the u8g2 library - just to make sure the display works properly.

Does the code work?

 

Hello Hans and thank you for the reply!

Indeed the section you highlighted is what I want to show on the welcome screen.

Yes the Program works perfectly, If I type anything in the void loop() section, it will show, but traced above what is shown already in the program so it turns out a mess.

I tried to copy your code an put it exactly under void setup() but it gives me a blank screen again, for 5 seconds, the duration you specified for testing, then the main program starts and shows on screen.

It's as if u8g2 is not recognized or identified under void setup(), only in the void loop() section, I wonder why...

What could be wrong or missing?

Ali

This post was modified 4 years ago by alj86

   
ReplyQuote
(@alj86)
Active Member
Joined: 4 years ago
Posts: 3
Topic starter  

Sorry made a mistake, I meant to say anything I put between u8g2.firstpage()  an u8g2.nextpage() is recognized and shows on screen but doesn't serve the purpose of a welcome screen unfortunately.

I haven't tried putting anything under void loop()

This post was modified 4 years ago by alj86

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2805
 

Ah that makes more sense now 😊 

I tried decoding the Reference Documentation of u8g2 (I do find the example for firstpage confusing).

What I read is that the content cannot be changed while running through the firstpage/nextpage loop.
I did find an explanation here with some examples and here.

Man this is confusing ... the 'firstpage' documentation states:

Description: This command is part of the (picture) loop which renders the content of the display. This command must be used together with nextPage. There are some restrictions: Do not change the content when executing this loop. Always redraw everything. It is not possible to redraw only parts of the content. The advantage is lesser RAM consumption compared to a full frame buffer in RAM, see sendBuffer.

Yet every example I found actually does change the content.
For example in the documentation of PageBuffer, where it literally states:

1. Call u8g2.firstPage().
2. Start a do-while loop
3. Inside the loop-body: Draw something with the usual draw commands.
4. Loop as long as u8g2.nextPage() returns true.

Either I'm not understanding the documentation, or there is something wrong with the documentation.

So I cannot give you a good fix for this problem.
However ... since the firstpage method is only done to save a little memory, maybe it is better and easier to understand to use the standard method of displaying info. From what I read this will be faster as well and not require a loop.

I have no experience with u8g2, but maybe change drawScreen to this to keep things simple (not sure how good/bad your controller is on memory with the full code):

(I removed the firstpage/netpage do-while of the code and added clearDisplay)

void drawScreen(float Input, float Seeing, float movingAverage)
{
  static int curPos = 0;
  static int graph[MAX_POINTS];
  static int graphavg[MAX_POINTS];

  int meterInput = int (round(Input * 10));
  float work = (Seeing * 100);

  if (work > 350)
    work = 350;

  int graphSeeing = int (round(work / 10));
  work = (movingAverage * 100);

  if (work > 300)
    work = 300;

  int graphmAverage = int (round(work / 10));

  if (curPos >= MAX_POINTS) {	// Shift array
    for (int s = 1; s < MAX_POINTS; s++) {
      graphavg[s - 1] = graphavg[s];
      graph[s - 1] = graph[s];
    }
    curPos = MAX_POINTS - 1;
  }

  graph[curPos] = graphSeeing;
  graphavg[curPos] = graphmAverage;
  curPos++;

  u8g2.clearDisplay();
  u8g2.setFont(u8g2_font_profont10_tr);
  u8g2.drawStr(1, 5 SolarSeeing:)
  int i = 0;
  int y = 0;
  u8g2.setFontMode(1);
  u8g2.setDrawColor(1);
  u8g2.setFontPosCenter();
  while (i < MAX_BARS) {
    y = MAX_BARS;
    while (y >= 0) {
      if (meterInput > i + METER_MIN_DISPLAY)
        if (i - y >= 0) {
          u8g2.drawXBM(METER_POS +
                 (i * METER_WIDTH),
                 METER_BOTTOM - y,
                 METER_WIDTH,
                 METER_HEIGHT,
                 meter_bits);
        }
      y--;
    }
    u8g2.drawXBM(METER_POS + (i * METER_WIDTH),
           METER_BOTTOM + 1, METER_WIDTH,
           METER_HEIGHT, graymeter_bits);
    i++;
  }
  if (meterInput >= 6)
    u8g2.drawXBM(METER_POS - SUN_WIDTH - 4,
           METER_BOTTOM - 5, SUN_WIDTH, SUN_HEIGHT,
           Sun);
  if (Input > 1.0)
    u8g2.drawStr(METER_POS - SUN_WIDTH - 10, METER_BOTTOM,
           "H");

  u8g2.drawHLine(128 - MAX_POINTS - 4, 63, MAX_POINTS + 4);
  u8g2.drawHLine(128 - MAX_POINTS - 4, 63 - 10, MAX_POINTS + 4);
  u8g2.drawHLine(128 - MAX_POINTS - 4, 63 - 20, MAX_POINTS + 4);
  u8g2.drawHLine(128 - MAX_POINTS - 4, 63 - 30, MAX_POINTS + 4);

  u8g2.drawStr(METER_POS, TEXT_BOTTOM,
         FormatStr("%01d" "." "%02d V",
             FLOAT_ARGS(Input, 100)));
  u8g2.setFont(u8g2_font_profont22_tr);
  u8g2.drawStr(0, TEXT_BOTTOM,
         FormatStr("%01d" "." "%02d\"",
             FLOAT_ARGS(Seeing, 100)));
  u8g2.drawVLine(128 - MAX_POINTS - 3, 29, 35);
  for (i = 0; i < MAX_POINTS; i++) {
    u8g2.drawVLine(128 - MAX_POINTS + i, 63 - graph[i],
             graph[i]);
    if (graphavg[i] > 0) {
      u8g2.setDrawColor(2);
      u8g2.drawVLine(128 - MAX_POINTS + i,
               63 - graphavg[i] - 1, 2);
      u8g2.setDrawColor(1);
    }
  }

  u8g2.setFont(u8g2_font_profont10_tr);

  u8g2.drawStr(0, 63 - 30, "3");
  u8g2.drawStr(0, 63 - 20, "2");
  u8g2.drawStr(0, 63 - 10, "1");
}

 

 

 


   
ReplyQuote
Share: