Sieben Segment Uhr

Moment!
Wenn ich die Bilder so anschaue, sehe ich RGBW LEDs. Gibt es WS2812 als RGBW? Das müssten doch SK6812 sein. Dann wäre das der falsche Sketch und das würde auch die Probleme mit der LED Anzahl erklären. Die brauchen mehr Daten!

Du kannst ja eventuell die Adafruit Neopixel Library testen. Die kann RGBW, bei der FastLED weiß ich es nicht.
Die Neopixel gibt es im Bibliotheksverwalter in der IDE. Da gibt es "RGBWstrandtest". Das könntest Du mal anpassen und testen.

Gruß, Jürgen

2 Likes

Nacherklährung:
RGB LEd brauchen 3x8 Bit Daten also 32 Bit. RGBW brauchen 4x8Bit. Wenn Du aber nur 40x32 Bit sendest dann sind das bei 4 Bit pro LED nur 22,5 LED

Wie versorgst Du die LED mit Strom?
Grüße Uwe

1 Like

FastLED kann schon nicht RGBW. Man muss es nur angeben. Zurzeit geht dein Code von GRB (Grün, Rot, Blau) aus.
Gerade nochmal in die Keywords geschaut:

# RGB orderings
RGB	LITERAL1
RBG	LITERAL1
GRB	LITERAL1
GBR	LITERAL1
BRG	LITERAL1
BGR	LITERAL1

Der Code kommt nicht von mir.

wenn man mit der Adafruit Neopixel probieren will, dann werfe ich meine Neopixel Library ins rennen
https://werner.rothschopf.net/202005_arduino_neopixel_display_en.htm

Ausgangsbasis wäre dann wohl der Sketch

30 clock basic

den man um einen RTC erweitern müsste, weil aktuell zeigt der nur wie man das Layout macht.

Edit:
eigentlich eh ganz gerade aus:

/* Noiasca Neopixel Display
   31 clock RTC
   handling HH MM SS as three separate displays
   reading RTC
   
   http://werner.rothschopf.net/202005_arduino_neopixel_display.htm
   
   by noiasca
   2021-11-09
*/

/*
   Segments are named and orded like this

          SEG_A
   SEG_F         SEG_B
          SEG_G
   SEG_E         SEG_C
          SEG_D          SEG_DP

  in the following constant array you have to define
  which pixels belong to which segment
*/

const byte ledPin = 12;                // Which pin on the Arduino is connected to the NeoPixels?
const byte numDigits = 2;              // How many digits (numbers) are available on each display
const byte startPixelHH = 0;           // the display starts with HH with the first pixel
const byte startPixelMM = 16;          // the MM are in the middle (start at 0 + digits for 10H + digits for H + 2 for the colon) 7+7+2
const byte startPixelSS = 32;          // seconds are on the far right, (7+7+2+7+7+2)
const byte pixelPerDigit = 7;          // all pixels, including decimal point pixels if available at each digit
const byte addPixels = 4;              // unregular additional pixels to be added to the strip (e.g. a double point for a clock 12:34:56)
const uint16_t ledCount(pixelPerDigit * numDigits * 3 + addPixels);

typedef uint8_t segsize_t;              // fit variable size to your needed pixels. uint8_t --> max 8 Pixel per digit
const segsize_t segment[8] {
  0b00000001,  // SEG_A
  0b00000010,  // SEG_B
  0b00000100,  // SEG_C
  0b00001000,  // SEG_D
  0b00010000,  // SEG_E
  0b00100000,  // SEG_F
  0b01000000,  // SEG_G
  0b00000000   // SEG_DP if you don't have a decimal point, just leave it zero
};

/*

// Variant for 16 LEDs per digit
const byte ledPin = 12;                // Which pin on the Arduino is connected to the NeoPixels?
const byte numDigits = 2;              // How many digits (numbers) are available on each display
const byte startPixelHH = 0;           // the display starts with HH with the first pixel
const byte startPixelMM = 32;          // the MM are in the middle (start at 0 + digits for 10H + digits for H + 2 for the colon)
const byte startPixelSS = 64;          // seconds are on the far right, therefore we need the highest pixel offset
const byte pixelPerDigit = 15;         // all pixels, including decimal point pixels if available at each digit
const byte addPixels = 4;              // unregular additional pixels to be added to the strip (e.g. a double point for a clock 12:34:56)
const uint16_t ledCount(pixelPerDigit * numDigits * 3 + addPixels);

typedef uint16_t segsize_t;              // fit variable size to your needed pixels. uint16_t --> max 16 Pixel per digit
const segsize_t segment[8] {
  0b0000000000000011,  // SEG_A
  0b0000000000001100,  // SEG_B
  0b0000000000110000,  // SEG_C
  0b0000000011000000,  // SEG_D
  0b0000001100000000,  // SEG_E
  0b0000110000000000,  // SEG_F
  0b0011000000000000,  // SEG_G
  0b1100000000000000   // SEG_DP if you don't have a decimal point, just leave it zero
};
*/

#include <Adafruit_NeoPixel.h>                                      // install Adafruit library from library manager
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800);    // create neopixel object like you commonly used with Adafruit

#include <Noiasca_NeopixelDisplay.h>                                     // download library from: http://werner.rothschopf.net/202005_arduino_neopixel_display.htm
// in this sketch we handle HH and MM as two individual displays:
Noiasca_NeopixelDisplay displayHH(strip, segment, numDigits, pixelPerDigit, startPixelHH);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displayMM(strip, segment, numDigits, pixelPerDigit, startPixelMM);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displaySS(strip, segment, numDigits, pixelPerDigit, startPixelSS);  // create display object, handover the name of your strip as first parameter!

#include "RTClib.h"  // by Adafruit tested with Version 1.12.5
RTC_DS3231 rtc;

void blinkColon()
{
  static uint32_t previousTimestamp = 0;
  static bool state = 0;
  uint32_t actualTimestamp = millis() / 500;
  if (actualTimestamp != previousTimestamp)
  {
    previousTimestamp = actualTimestamp;
    strip.setPixelColor(pixelPerDigit * 2 + 0, 0x0000FF * state);  
    strip.setPixelColor(pixelPerDigit * 2 + 1, 0x0000FF * state);  
    strip.setPixelColor(pixelPerDigit * 4 + 2, 0x0000FF * state);  
    strip.setPixelColor(pixelPerDigit * 4 + 3, 0x0000FF * state);
    strip.show();
    state = !state;
  }
}

void updateSecond()
{
  static uint32_t previousSecond = -1;
  DateTime now = rtc.now();
  uint32_t actualSecond = now.second() ;
  if ( actualSecond != previousSecond)
  {
    previousSecond = actualSecond;
    Serial.print('s');
    Serial.println(actualSecond);
    displaySS.setCursor(0);
    if (actualSecond < 10) displaySS.print("0");
    displaySS.print(actualSecond);
  }
}

void updateMinute()
{
  static uint32_t previousMinute = -1;
  DateTime now = rtc.now();
  uint32_t actualMinute = now.minute() ;
  if ( actualMinute != previousMinute)
  {
    previousMinute = actualMinute;
    Serial.print('m');
    Serial.println(actualMinute);
    displayMM.setCursor(0);
    if (actualMinute < 10) displayMM.print("0");
    displayMM.print(actualMinute);
  }
}

void updateHour()
{
  static uint32_t previousHour = -1;
  DateTime now = rtc.now();
  uint32_t actualHour = now.hour();
  if ( actualHour != previousHour)
  {
    previousHour = actualHour;
    Serial.print('h');
    Serial.println(actualHour);
    displayHH.setCursor(0);
    if (actualHour < 10) displayHH.print(" ");
    displayHH.print(actualHour);
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println(F("\nNoiascaNeopixelDisplay\n31 clock two displays"));

  strip.begin();                   // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();                    // Turn OFF all pixels ASAP
  strip.setBrightness(50);         // Set BRIGHTNESS to about 1/5 (max = 255)
  strip.clear();                   // clears the full strip (all displays assigned to this strip!)

  displayHH.setColorFont(0xAAAA00);
  displayMM.setColorFont(0x880044);

  Serial.println(F("Print 8888 on your display"));
  displayHH.print("88");
  displayMM.print("88");
  displaySS.print("88");

  if (! rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
    displayHH.print(" E");
    displayMM.print("rr");
    displaySS.print("or");
    delay(1000); // dirty delay to give time to read message
  }

  if (rtc.lostPower()) {
    Serial.println(F("RTC lost power, let's set the time!"));
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time
    //                     YYYY MM  DD  HH MM SS
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
    displayHH.print(" S");
    displayMM.print("ET");
    displaySS.print("  ");
    delay(1000); // dirty delay to give time to read message
  }
}

void loop()
{
  blinkColon();
  updateSecond();
  updateMinute();
  updateHour();
  // put here other code which needs to run:
}

Vorsicht:
Bei mir beginnt die Kette an Neopixels von Links (also mit der 10er Stunde).
Nach genauem Studium des Links sollte es klar sein, wie man das umstellt wenn benötigt.

Eigentlich nicht, aber manche Händler verwenden "WS2812" als Marketingnamen, nicht als wirkliche technische Spezifikation. Wenn man was Spezielles sucht, nervt das total :face_with_symbols_over_mouth:

Meine Frau packt gerade Geschenke ein, da mache ich dann auch mal eins, mit gleich noch mit ein paar Feinheiten gepimpt. Getestet mit RGB (WS2815B), nicht getestet mit RGBW:

#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include "RTClib.h"

#define PIN 6
#define NUMPIXELS 30
//Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

const uint32_t colorON = pixels.Color(255, 180, 0);
const uint32_t colorOFF = pixels.Color(0, 0, 0);
const uint32_t colorDOT = pixels.Color(0, 0, 255);

RTC_DS3231 rtc;

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

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  pixels.begin();
  // nur zum Farbtest
  displayTime(0, 8, pixels.Color(255, 0, 0));  // Minute rechts rot
  displayTime(7, 8, pixels.Color(0, 255, 0));  // Minute links grün
  pixels.setPixelColor(14, colorDOT);          // Punkte blau
  pixels.setPixelColor(15, colorDOT);
  displayTime(16, 8, colorON);                 // Stunde rechts
  displayTime(23, 8, colorON);                 // Stunde links
  // Test Ende
  pixels.show();
  delay(2000);
}

void ausgabe_zahl(byte zahl, char trenner){
  if(zahl<10) Serial.print('0');
  Serial.print(zahl, DEC);
  Serial.print(trenner);
}

void loop () {
  uint32_t jetzt = millis();
  static uint32_t vorhin = 0;
  const uint32_t intervall = 1000;
  static byte m_alt = 255;
  
  if (jetzt - vorhin >= intervall) {
    vorhin = jetzt;
    DateTime now = rtc.now();
    Serial.print(now.year(), DEC);
    Serial.print('/');
    ausgabe_zahl(now.month(), '/');
    ausgabe_zahl(now.day(), ' ');
    ausgabe_zahl(now.hour(), ':');
    ausgabe_zahl(now.minute(), ':');
    ausgabe_zahl(now.second(), '\n');

    if (now.minute() != m_alt) {
      m_alt = now.minute();
      
      byte hl = now.hour() / 10;
      byte hr = now.hour() % 10;
      byte ml = now.minute() / 10;
      byte mr = now.minute() % 10;

      displayTime(0, mr, colorON);
      displayTime(7, ml, colorON);
      displayTime(16, hr, colorON);
      displayTime(23, hl, colorON);
    }
    displayDots();
    pixels.show();
  }
}

void displayDots() {
  static bool dotONoff = false;

  dotONoff = !dotONoff;
  if (dotONoff) {
    pixels.setPixelColor(14, colorDOT);
    pixels.setPixelColor(15, colorDOT);
  } else {
    pixels.setPixelColor(14, colorOFF);
    pixels.setPixelColor(15, colorOFF);
  }
}

void displayTime(byte startindex, byte number, uint32_t color) {
  byte numbers[] = {
    0b00111111, // 0
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111, // 9
  };

  for (int i = 0; i < 7; i++) {
    pixels.setPixelColor(i + startindex, ((numbers[number] & 1 << i) == 1 << i) ? color : colorOFF);
  }
}

:gift:

@leonnek11: Funktioniert es bei Dir mit RGBW?

Die Farben kannst Du nach eigenem Geschmack wählen nach dem Schema pixels.Color(rot, grün, blau) oder pixels.Color(rot, grün, blau, weiß).

Habe jetzt gerade mal den RGBW Strandtest Code ausgespielt und da funktionieren alle Leds wenn ich auf 30 Leds einstelle.
Also verstehe ich das jetzt so das das SK6812 Leds sind ?

Habe nur die Arduino Nano als Spannungsversorgung

Ok also ist der Code nicht der richtige für die Leds.
Kann ich selber was in dem Code ändern das die trotzdem funktionieren ?

Du kannst dir gar nicht vorstellen wie sehr ich mich gerade freue.
Nach einem Jahr ausprobieren funktioniert die Uhr endlich.

Mit der FastLED Bibliothek soll es über Umwege auch gehen. Es gibt auch das Schlüsselwort SK6812 in der Bibliothek. Ich habe mich aber nicht näher damit beschäftigt.

Aber ich denke mit der Adafruit_NeoPixel.h gehst du den für dich einfacheren Weg.

"SK6812" ist ein RGB LED mit integrierten Treiber.
"SK6812RGBW-XX" ist ein RGBW LED mit Treiber. XX geben die Farbe des weißen Anteils an. NW, BW und SW (natural withe, blue-withe, warm sunlight)
Leider habe ich im Datenblatt nicht den Stromverbrauch der LED gefunden , sondern nur den max Ausgangsstrom der Ausgänge für die LEDs.

Würde aber dennoch mit 20mA pro LED rechnen also 80mA pro LED.

Ich glaube um 08:08 sind am meisten Segmente an; also 28 Stück.
USB kann 500mA liefern; Der Spannungsstabilisator am Nano nur 150mA. Beides ist zuwenig um die LED sicher mit Strom zu versorgen.

Du brauchst eine 5V Spannungsversorgung mit 2,5A.

Grüße Uwe

Ok gut zu wissen muss ich mir dann noch bestellen

Sehr schön, so soll's sein :slightly_smiling_face:

Mit strip.setBrightness(50); in setup() kannst Du die Helligkeit stromsparend reduzieren.