Struggling with C

Thread Starter

Torbek

Joined Apr 19, 2019
83
Hi folks, so learning C, using DeepSeek to help me learn, as I feel this is the best course of action for me.
DS has produced some reasonable attempts so far, although it does seem to make very basic, dare I say human errors at times!

So in this example snippets of code, why would one code never produce a display error (display works) whilst another piece of code always produces a display error and will not display anything...? Is this a compiling issue?

None working example - always reports disconnected display :
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <EEPROM.h>

// =============================================
// Hardware Configuration
// =============================================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define SCREEN_ADDRESS 0x3D // I2C address for OLED
#define OLED_RESET 10 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define BME280_ADDRESS 0x76 // I2C address for BME280
Adafruit_BME280 bme;

// Button pins (using internal pull-up)
#define BUTTON_PLUS 2
#define BUTTON_MINUS 3
#define BUTTON_ENTER 4

// Output pins
#define HUM_OUTPUT_PIN 9  // PWM output for humidity control
#define ALARM_OUTPUT_PIN 7     // Digital output for alarm

// =============================================
// Default Settings (adjustable)
// =============================================
#define DEFAULT_TARGET_HUM 55    // Default target hum
#define DEFAULT_HIGH_T_ALARM 35    // Default high talarm
#define DEFAULT_LOW_TEMP_ALARM 15     // Default low t alarm
#define DEFAULT_ALARM_ENABLED true    // Default alarm state
#define PWM_FREQUENCY 108000          // PWM frequency in Hz (108kHz)
#define PWM_DUTY_CYCLE 10             // Default PWM duty cycle (10%)

// =============================================
// EEPROM Addresses
// =============================================
#define EEPROM_TARGET_HUMIDITY 0    // 1 byte
#define EEPROM_HIGH_TEMP_ALARM 1    // 1 byte
#define EEPROM_LOW_TEMP_ALARM 2     // 1 byte
#define EEPROM_ALARM_ENABLED 3      // 1 byte

// =============================================
// System Parameters (don't change)
// =============================================
#define HUMIDITY_MIN 1
#define HUMIDITY_MAX 65
#define TEMP_MIN 4
#define TEMP_MAX 65
#define ENTER_HOLD_TIME 1000  // 1 second hold time for enter button
#define BUTTON_DEBOUNCE 50    // Debounce time in ms
#define FAST_REPEAT_DELAY 3000 // Time before button repeat speeds up (ms)

// =============================================
// Global Variables
// =============================================
struct SystemSettings {
  uint8_t targetHumidity;
  uint8_t highTempAlarm;
  uint8_t lowTempAlarm;
  bool highAlarmEnabled;
  bool lowAlarmEnabled;
};

SystemSettings settings;

// Button states
bool buttonPlusPressed = false;
bool buttonMinusPressed = false;
bool buttonEnterPressed = false;
unsigned long buttonPlusTime = 0;
unsigned long buttonMinusTime = 0;
unsigned long buttonEnterTime = 0;

// System state
enum MenuState { MAIN_SCREEN, SET_HUMIDITY, SET_HIGH_TEMP, SET_LOW_TEMP, SET_ALARM_ENABLE };
MenuState currentMenu = MAIN_SCREEN;
bool outputActive = false;
bool alarmActive = false;
bool tempAlarmFlash = false;
unsigned long lastFlashTime = 0;
const int flashInterval = 500; // Flash interval for alarm (ms)

// =============================================
// Setup Function
// =============================================
void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  Serial.println(F("Humidistat"));


  // Initialize OLED
  pinMode(OLED_RESET, OUTPUT);
  digitalWrite(OLED_RESET, LOW);
  delay(10);
  digitalWrite(OLED_RESET, HIGH);
  delay(10);

  // Initialize display
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
 
  // Initialize BME280 sensor
  if (!bme.begin(BME280_ADDRESS)) {
    Serial.println(F("Could not find a valid BME280 sensor, check wiring!"));
    while (1);
  }
 
  // Set up buttons with internal pull-up
  pinMode(BUTTON_PLUS, INPUT_PULLUP);
  pinMode(BUTTON_MINUS, INPUT_PULLUP);
  pinMode(BUTTON_ENTER, INPUT_PULLUP);
 
  // Set up outputs
  pinMode(HUM_OUTPUT_PIN, OUTPUT);
  pinMode(ALARM_OUTPUT_PIN, OUTPUT);
 
  // Configure PWM frequency for D9
  TCCR1A = _BV(COM1A1) | _BV(WGM10); // Fast PWM, 8-bit
  TCCR1B = _BV(WGM12) | _BV(CS10);   // No prescaler (16MHz/1 = 16MHz)
  OCR1A = (PWM_DUTY_CYCLE * 255) / 100; // Set duty cycle
 
  // Load settings from EEPROM or use defaults
  loadSettings();
 
  // Initial display
  display.clearDisplay();
  display.display();
}


Working example - ignores disconnected display:
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_BME280.h>
#include <EEPROM.h>

// Pin Definitions
#define BUTTON_UP 2       // Button 1 - Count up
#define BUTTON_DOWN 3     // Button 2 - Count down
#define BUTTON_SELECT 4   // Button 3 - Select
#define OUTPUT_PIN 5      // Main control output pin
#define PULSE_OUTPUT_PIN 9 // 108kHz pulsed output (must be Timer1 compatible)
#define OLED_RESET 10     // Reset pin for OLED

// Display Settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// EEPROM Address Definitions
#define EEPROM_ADDR_TARGET 0
#define EEPROM_ADDR_PULSE 2

// Sensor
Adafruit_BME280 bme;

// Constants
#define HYSTERESIS 2.0           // ±2% hysteresis
#define MIN_PULSE_WIDTH 1        // 1% minimum duty cycle
#define MAX_PULSE_WIDTH 50       // 50% maximum duty cycle
#define PULSE_FREQUENCY 108000   // 108kHz frequency
#define DEBOUNCE_DELAY 50        // Button debounce time (ms)
#define LONG_PRESS_TIME 1000     // Long press duration (ms)
#define STARTUP_PRESS_TIME 2000  // Press time during startup to enter pulse settings
#define INITIAL_SCROLL_DELAY 300 // Delay before fast scrolling starts (ms)
#define FAST_SCROLL_INTERVAL 100 // Interval during fast scrolling (ms)

// Global Variables
float currentTemp = 0;
float currentHumidity = 0;
int targetHumidity = 60;         // Default target humidity
int pulseWidthPercent = 10;      // Default pulse width (10%)
bool settingMode = false;
bool pulseSettingMode = false;   // Startup settings mode
bool outputState = false;
unsigned long lastDisplayUpdate = 0;
unsigned long lastBlink = 0;
unsigned long lastButtonCheck = 0;
const unsigned long buttonCheckInterval = 20; // Check buttons every 20ms
bool blinkState = false;

// Function declarations
void loadSettings();
void saveSettings();
void readSensorData();
void checkHumidity();
void updatePulseOutput();
void handleButtons();
void updateDisplay();
void adjustValue(int direction);

void setup() {
  Wire.setClock(100000L);
                                  
  Serial.begin(9600);
  Serial.println(F("Humidistat"));

  // Initialize OLED
  pinMode(OLED_RESET, OUTPUT);
  digitalWrite(OLED_RESET, LOW);
  delay(10);
  digitalWrite(OLED_RESET, HIGH);
  delay(10);

  // Initialize pins
  pinMode(BUTTON_UP, INPUT_PULLUP);
  pinMode(BUTTON_DOWN, INPUT_PULLUP);
  pinMode(BUTTON_SELECT, INPUT_PULLUP);
  pinMode(OUTPUT_PIN, OUTPUT);
  digitalWrite(OUTPUT_PIN, LOW);


  // Improved startup button check
  bool enteredPulseMode = false;
  unsigned long buttonPressStart = millis();
                          
 
  // Check if button is pressed at startup (with debounce)
  if (digitalRead(BUTTON_SELECT) == LOW) {
    delay(50); // Initial debounce delay
    // If still pressed after debounce, wait for hold time
                        
      
                                            
    while (digitalRead(BUTTON_SELECT) == LOW) {
      if (millis() - buttonPressStart > STARTUP_PRESS_TIME) {
        enteredPulseMode = true;
        pulseSettingMode = true;
        break;
      }
    }
    // Wait for button release with debounce
    while (digitalRead(BUTTON_SELECT) == LOW); // Wait for physical release
                            
    delay(50); // Debounce release
      
    
  }
  // Configure Timer1 for 108kHz PWM on pin 9
  pinMode(PULSE_OUTPUT_PIN, OUTPUT);
  TCCR1A = _BV(COM1A1) | _BV(WGM11);
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
  ICR1 = F_CPU / PULSE_FREQUENCY;
  OCR1A = 0;

  // Initialize BME280 sensor
  if (!bme.begin(0x76)) {
    Serial.println(F("Could not find BME280 sensor!"));
    while (1);
  }
 

nsaspook

Joined Aug 27, 2009
16,271
IMO, Turn-off DeepSeek. It's just giving poor answers, not helping you learn how to program in C or any other language.

They are useful tools, for those that already know programming.
 

MrChips

Joined Oct 2, 2009
34,698
You need to take a simpler, step-by-step approach to learning programming.
Begin with a working piece of code. Then add one function at a time.
C:
void init(void)
{
}

void main_loop(void)
{
}

void main(void)
{
  init();
  while(1)
  {
    main_loop();
  }
}
 

panic mode

Joined Oct 10, 2011
4,929
there a so many ways this can go sideways.
first of all you need to make sure that your wiring is correct.
then confirm that it is correct display size (128x32, 128x64 etc).

then you need to make sure that I2C address is correct. if address is not confirmed, use I2C scan to detect connected devices
i had couple of displays that had wrong address shown on the silkscreen.
1743425906781.png


for example:
Scan_I2C.ino:
// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// --------------------------------------

#include <Wire.h>

// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire

void setup() {
  WIRE.begin();

  Serial.begin(9600);
  while (!Serial)
     delay(10);
  Serial.println("\nI2C Scanner");
}


void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    WIRE.beginTransmission(address);
    error = WIRE.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}
and if all of the above is ok, why do you think that your display should show anything? because that code configured bunch of things and when it gets to display it CLEARS it...
this will make screen blank::
  // Initial display
  display.clearDisplay();
  display.display();
 
Last edited:

panic mode

Joined Oct 10, 2011
4,929
and if you want to see some example on using Adafruit library to control I2C display, why not use Adafruit example?
Code:
/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x64 pixel display using SPI to communicate
 4 or 5 pins are required to interface.

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

/* Comment out above, uncomment this block to use hardware SPI
#define OLED_DC     6
#define OLED_CS     7
#define OLED_RESET  8
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  &SPI, OLED_DC, OLED_RESET, OLED_CS);
*/

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }


  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines

  testdrawrect();      // Draw rectangles (outlines)

  testfillrect();      // Draw rectangles (filled)

  testdrawcircle();    // Draw circles (outlines)

  testfillcircle();    // Draw circles (filled)

  testdrawroundrect(); // Draw rounded rectangles (outlines)

  testfillroundrect(); // Draw rounded rectangles (filled)

  testdrawtriangle();  // Draw triangles (outlines)

  testfilltriangle();  // Draw triangles (filled)

  testdrawchar();      // Draw characters of the default font

  testdrawstyles();    // Draw 'stylized' characters

  testscrolltext();    // Draw scrolling text

  testdrawbitmap();    // Draw a small bitmap image

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn circle
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(;;) { // Loop forever...
    display.clearDisplay(); // Clear the display buffer

    // Draw each snowflake:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display(); // Show the display buffer on the screen
    delay(200);        // Pause for 1/10 second

    // Then update coordinates of each flake...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}
 
Top