Große LED Uhr bauen

Hallo ich bin Achim

ich versuche seit Wochen ein bestehendes Programm für eine BIG LED Clock für meine Bedürfnisse zu ändern.

Doch leider scheitere ich immer wieder, kann mir jemand mit Ahnung auf die Sprünge helfen bitte.

Beim bestehenden Programm wird pro Digit eine LED angesteuert. da ich aus einem anderen Projekt aber schon eine Uhr gebaut habe würde ich es gerne auf 3 LEDs pro Digit ändern.

Ich würde mich sehr freuen wenn mich jemand auf die Spur bringt.

Gruss Achim

sketch_apr29a.ino (9.85 KB)

Ist hier eine Frage versteckt?

felsdrache:
Ich würde mich sehr freuen wenn mich jemand auf die Spur bringt.

Ja, z.B. setze deinen Sketch hier direkt ins Forum in Code-Tags.
Dann ist dieser von allen besser lesbar.
Verwende dazu die Schaltfläche </> oben links im Editorfenster oder setze [ code ] vor den Sketch und [ / code] hinter den Sketch, ohne die Leerzeichen.

mach eine Zeichnung von deinem Display und beschreibe wo jedes Pixel ist.

Blatt Papier gut lesbar reicht.

Außerdem könntest du dir diesen Thread anschauen, das ist imho 90% dessen was es braucht drinnen:

https://forum.arduino.cc/index.php?topic=668096.0

Hi

30 LED klingt nach 4 Ziffern + 2 Punkte - korrekt?

Da die FastLED benutzt wird, hängen sämtliche LED an einem Datenpin.
Sofern Du Deine LEDs nicht kreuz und quer verlötet hast, musst Du doch 'nur' statt
0 -> 0
1 -> 3
2 -> 6
...
29 -> 87 (Ursprungswert x 3)
als Start-LED nehmen und ab dort 3 Stück einfärben.

Wenn Du Deine Segmente anders aufgeteilt hast, als in dem Sketch - baue eine Übersetzungstabelle.
Dort wirst Du dann aber für jedes Segment den Startwert angeben müssen - braucht ggf etwas mehr Platz.

MfG

PS: Sketch nur in den ersten Zeilen überflogen und aus der LED-Anzahl auf den Aufbau getippt.

PS: der Sketch ist >9kB - Das wird Nicht mit Code-Tags :slight_smile: (schon Die brauchen 13 Byte, befürchte ich)

postmaster-ino:
PS: der Sketch ist >9kB - Das wird Nicht mit Code-Tags :slight_smile: (schon Die brauchen 13 Byte, befürchte ich)

wenn man den Kommantar am Anfang ausspart, ist der Sketch schon über 1500 Zeichen kürzer :wink:

postmaster-ino:
PS: der Sketch ist >9kB - Das wird Nicht mit Code-Tags :slight_smile: (schon Die brauchen 13 Byte, befürchte ich)

Wo ist das Problem ?

Auch das kann der TO üben.

Also kurz was ich denke zu wissen. Ich brauche 86 LEDs und die Dots liegen auf 42 und 43.
Nur mit dem Rest schwimme ich. Muss ich das mit den byte numbers 21 mal wiederholen oder nur die richtigen nummern eintragen?

void displaySegments(int startindex, int number) {

  byte numbers[] = {
    0b00111111, // 0    
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111, // 9   
    0b01100011, // º              10
    0b00111001, // C(elcius)      11
    0b01011100, // º lower        12
    0b00000000, // Empty          13
    0b01110001, // F(ahrenheit)   14
  };

  for (int i = 0; i < 7; i++) {
    LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
  }

Hi

Okok ... die Punkte gehen an Euch

In den Funktionen, in Denen direkt in das LED-Array geschrieben wird (displaySegments(x,y); displayDots(x); ) müsste man die Umsetz-Tabelle zwischenbringen.
Das würde ich in eine Funktion auslagern - aka
Statt
LEDs[14] = colorMODE == 0 ? colorCRGB : colorCHSV;
die eigene Funktion aufrufen
setLEDs(14,colorMODE == 0 ? colorCRGB : colorCHSV);
Diese kümmert sich drum, daß '14' nun zu den drei Pixeln wird, Die dafür nun leuchten sollen.

MfG

#include <DHT.h>
#include <DHT_U.h>
#include <FastLED.h>
#include <Wire.h>
#include "RTClib.h"
#include <SoftwareSerial.h>
#include "Timer.h"

#define DHTPIN 12
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

#define NUM_LEDS 86     
#define DATA_PIN 6
CRGB LEDs[NUM_LEDS];

SoftwareSerial BTserial(8, 9);
RTC_DS3231 rtc;
Timer t1;
Timer t2;
Timer t3;

String btBuffer;
CRGB colorCRGB = CRGB::Red;           // Change this if you want another default color, for example CRGB::Blue
CHSV colorCHSV = CHSV(95, 255, 255);  // Green
CRGB colorOFF  = CRGB(0,0,0);      // Color of the segments that are 'disabled'. You can also set it to CRGB::Black
volatile int colorMODE = 1;           // 0=CRGB, 1=CHSV, 2=Constant Color Changing pattern
volatile int mode = 0;                // 0=Clock, 1=Temperature, 2=Humidity, 3=Scoreboard, 4=Time counter
volatile int scoreLeft = 0;
volatile int scoreRight = 0;
volatile long timerValue = 0;
volatile int timerRunning = 0;

#define blinkDots   1                 // Set this to 1 if you want the dots to blink in clock mode, set it to value 0 to disable
#define hourFormat  24                // Set this to 12 or to 24 hour format
#define temperatureMode 'C'           // Set this to 'C' for Celcius or 'F' for Fahrenheit

void setup () {

  // Initialize LED strip
  FastLED.delay(3000);

  // Check if you're LED strip is a RGB or GRB version (third parameter)
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(LEDs, NUM_LEDS);

  Serial.begin(9600);
  while (!Serial) { /* Wait until serial is ready */ }

  BTserial.begin(9600);
  Serial.println("BTserial started at 9600");

  dht.begin();

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

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
    
  t1.every(1000 * 29, refreshDisplay); 
  t2.every(1000, refreshTimer);
  t3.every(50, updateHue);
  refreshDisplay();
}

void loop () {
  
  t1.update(); 
  t2.update();
  t3.update();

  if (BTserial.available())
  {
    char received = BTserial.read();
    btBuffer += received; 

    if (received == '|')
    {
        processCommand();
        btBuffer = "";
    }
  }
}

void updateHue() {
  if (colorMODE != 2)
    return;
    
  colorCHSV.sat = 255;
  colorCHSV.val = 255;
  if (colorCHSV.hue >= 255){
    colorCHSV.hue = 0;
  } else {
    colorCHSV.hue++;
  }
  refreshDisplay();
}

void refreshDisplay() {
  switch (mode) {
    case 0:
      displayClock();
      break;
    case 1:
      displayTemperature();
      break;
    case 2:
      displayHumidity();
      break;
    case 3:
      displayScoreboard();
      break;      
    case 4:
      // Time counter has it's own timer
      break;
    default:   
      break; 
  }
}

void refreshTimer() {

  if (mode == 0 && blinkDots == 1) {    
    displayDots(3);
  } else if (mode == 4 && timerRunning == 1 && timerValue < 6000) {
    timerValue++;

    int m1 = (timerValue / 60) / 10 ;
    int m2 = (timerValue / 60) % 10 ;
    int s1 = (timerValue % 60) / 10;
    int s2 = (timerValue % 60) % 10;
  
    displaySegments(0, s2); 
    displaySegments(7, s1);
    displaySegments(16, m2);    
    displaySegments(23, m1);  
    displayDots(0);  
    FastLED.show();
  }
}

void processCommand(){

  if (btBuffer.startsWith("RGBD")) {
    long R = getValue(btBuffer, ',', 1).toInt();
    long G = getValue(btBuffer, ',', 2).toInt();
    long B = getValue(btBuffer, ',', 3).toInt();
    long D = getValue(btBuffer, ',', 4).toInt();
    colorCRGB.red = R;
    colorCRGB.green = G;
    colorCRGB.blue = B;
    colorMODE = 0;
    if (D > 0) FastLED.setBrightness(D); 
  } else if (btBuffer.startsWith("HSVD")) {
    long H = getValue(btBuffer, ',', 1).toInt();
    long S = getValue(btBuffer, ',', 2).toInt();
    long V = getValue(btBuffer, ',', 3).toInt();
    long D = getValue(btBuffer, ',', 4).toInt();
    colorCHSV.hue = H;
    colorCHSV.sat = S;
    colorCHSV.val = V;
    colorMODE = 1;
    if (D > 0) FastLED.setBrightness(D);
  } else if (btBuffer.startsWith("RTC")) {
    long y = getValue(btBuffer, ',', 1).toInt();
    long m = getValue(btBuffer, ',', 2).toInt();
    long d = getValue(btBuffer, ',', 3).toInt();
    long h = getValue(btBuffer, ',', 4).toInt();
    long mm = getValue(btBuffer, ',', 5).toInt();
    long s = getValue(btBuffer, ',', 6).toInt();
    rtc.adjust(DateTime(y, m, d, h, mm, s));
    Serial.println("DateTime set");
  } else if (btBuffer.startsWith("CLOCK")) {
    mode = 0;    
  } else if (btBuffer.startsWith("TEMPERATURE")) {
    mode = 1;    
  } else if (btBuffer.startsWith("HUMIDITY")) {
    mode = 2;
  } else if (btBuffer.startsWith("SCOREBOARD")) {
    scoreLeft = getValue(btBuffer, ',', 1).toInt();
    scoreRight = getValue(btBuffer, ',', 2).toInt();
    mode = 3;    
  } else if (btBuffer.startsWith("STARTTIMER")) {
    timerValue = 0;
    timerRunning = 1;
    mode = 4;    
  } else if (btBuffer.startsWith("STOPTIMER")) {
    timerRunning = 0;
    mode = 4;    
  } else if (btBuffer.startsWith("CHANGINGPATTERN")) {
    colorMODE = 2;
  }
  
  refreshDisplay();
}

void displayClock() {   
  DateTime now = rtc.now();

  int h  = now.hour();
  if (hourFormat == 12 && h > 12)
    h = h - 12;
  
  int hl = (h / 10) == 0 ? 13 : (h / 10);
  int hr = h % 10;
  int ml = now.minute() / 10;
  int mr = now.minute() % 10;

  displaySegments(0, mr);    
  displaySegments(7, ml);
  displaySegments(16, hr);    
  displaySegments(23, hl);  
  displayDots(0);  
  FastLED.show();
}

void displayTemperature() {
  float tmp = dht.readTemperature(temperatureMode == 'F' ? true : false);

  if (isnan(tmp)) {
    Serial.println("Failed to read from DHT sensor!");
  } else {
    int tmp1 = tmp / 10;
    int tmp2 = ((int)tmp) % 10;
    displaySegments(23, tmp1);    
    displaySegments(16, tmp2);
    displaySegments(7,  10);    
    displaySegments(0, (temperatureMode == 'F' ? 14 : 11));
    displayDots(1);  
    FastLED.show();    
  }  
}

void displayHumidity() {
  float hum = dht.readHumidity();

  if (isnan(hum)) {
    Serial.println("Failed to read from DHT sensor!");
  } else {
    int hum1 = hum / 10;
    int hum2 = ((int)hum) % 10;
    displaySegments(23, hum1);    
    displaySegments(16, hum2);
    displaySegments(7,  10);    
    displaySegments(0,  12);
    displayDots(1);  
    FastLED.show();    
  }  
}

void displayScoreboard() {
  int s1 = scoreLeft % 10;
  int s2 = scoreLeft / 10;
  int s3 = scoreRight % 10;
  int s4 = scoreRight / 10;
  displaySegments(0, s3);    
  displaySegments(7, s4);
  displaySegments(16, s1);    
  displaySegments(23, s2);
  displayDots(2);  
  FastLED.show();  
}

void displayDots(int dotMode) {
  // dotMode: 0=Both on, 1=Both Off, 2=Bottom On, 3=Blink
  switch (dotMode) {
    case 0:
      LEDs[14] = colorMODE == 0 ? colorCRGB : colorCHSV;
      LEDs[15] = colorMODE == 0 ? colorCRGB : colorCHSV; 
      break;
    case 1:
      LEDs[14] = colorOFF;
      LEDs[15] = colorOFF; 
      break;
    case 2:
      LEDs[14] = colorOFF;
      LEDs[15] = colorMODE == 0 ? colorCRGB : colorCHSV; 
      break;
    case 3:
      LEDs[14] = (LEDs[14] == colorOFF) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
      LEDs[15] = (LEDs[15] == colorOFF) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
      FastLED.show();  
      break;
    default:
      break;    
  }
}

void displaySegments(int startindex, int number) {

  byte numbers[] = {
    0b00111111, // 0    
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111, // 9   
    0b01100011, // º              10
    0b00111001, // C(elcius)      11
    0b01011100, // º lower        12
    0b00000000, // Empty          13
    0b01110001, // F(ahrenheit)   14
  };

  for (int i = 0; i < 7; i++) {
    LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
  } 
}

String getValue(String data, char separator, int index) {
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

ich muss das DisplaySegment auf 0 , 21 , 44 , 65

Hi

Habe mir Deine letzten zwei Posts jetzt 3x durchgeschaut ... HÄH?

... denke ...

auch wenn sich der TO nicht mehr meldet, jetzt hab ich den Sketch aus dem verlinkten Thread eine Library für Neopixel Displays gemacht. Da der Sketch größer und die Verwendung daher auch umfangreicher geworden ist, habe ich das auf meiner HP beschrieben.

https://werner.rothschopf.net/202005_arduino_neopixel_display_en.htm

Bilderchen gibts dort auch:
display14.png

display14.png

Chapeau!

Ja Hallo

Vieleicht kann mir doch noch jemand einen Tip geben wie ich "diese" Programm ändern kann.

Wie gesagt die Uhr selber besteht schon und zwar mit insgesamt 86 LEDs mit 21 LED pro Segment und die DOTs auf 42 und 43.
Mein Problem wenn ich es so ändere sind die BITs von 16-20 immer auf 1

void displaySegments(int startindex, int number) {

  byte numbers[] = {
   
 0x0003FFFF, // 0
 0x000001F8, // 1
 0x001C7E3F, // 2
 0x001C0FFF, // 3
 0x001F81F8, // 4
 0x001F8FC7, // 5
 0x001FFFC7, // 6
 0x000001FF, // 7
 0x001FFFFF, // 8
 0x001F81FF,  // 9
 0b011110000001111, // º              10
 0b000111111000011, // C(elcius)      11
 0b011001111110000, // º lower        12
 0b000000000000000, // Empty          13
 0b011111100000011, // F(ahrenheit)   14

  };
for (int i = 0; i < 21; i++) {
   
    LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
  }

das:

0b011110000001111, // º 10
0b000111111000011, // C(elcius) 11
0b011001111110000, // º lower 12
0b000000000000000, // Empty 13
0b011111100000011, // F(ahrenheit) 14

wird auch nicht wirkich in ein byte passen!
byte numbers[] = {

warum nimmst nicht ein uint16_t?

ACHTUNG

Die 0xabcdef12 da drüber riechen auch 'etwas' größer als Byte.
Ob wir Da noch mit uint16_t auskommen?? Ich weiß ja nicht ... (doch, ich weiß ... bräuchte 32 Bit)

MfG