Open Eka1911 opened 3 years ago
numbers is an array of type "long", which is limited to 32 bits, and with 5 LEDs, you'd need 35 bits.
try change to "long long"
@helpquick
numbers is an array of type "long", which is limited to 32 bits, and with 5 LEDs, you'd need 35 bits.
try change to "long long"
What if you want to reduct to 2 leds?
@niall-cooley
What if you want to reduct to 2 leds?
There's a number of places in the code which need to be updated if you change the number of LEDs, e.g. start indexes will all need to be updated, the pattern in the numbers[] array need to be updated, etc.
@helpquick Yeah I was thinking that Ive updated the number of LED's and the indexes. Just trying to work out the pattern in numbers[] now :)
_8 _9
_7 10
_6 11
13 12
_5 _0
_4 _1
_3 _2
your bit patterns would like like the above. Bit 0 - 1st LED, bit 13 = last LED
So, if yo put a 1 next to the LEDs which would be lit for a given number, you can put a 1 in the bit lit, and 0 in the unlit bit.
I worked backwards from bit 13, so you can type it in order. for a 1, it is 0 0 1 1 0 0 0 0 0 0 0 0 1 1
A quick go at it is below:
0b00111111111111 // 0
0b00110000000011 // 1
0b11111100111100 // 2
0b11111100001111 // 3
0b11110011000011 // 4
0b11001111001111 // 5
0b11001111111111 // 6
0b00111100000011 // 7
0b11111111111111 // 8
0b11111111001111 // 9
Or something like that.
@helpquick Thank you!
So what if you wanted to use 7 LEDs per segment, my issue is that long long won't work and you can't use double because of this. for (byte i=0; i<49; i++){ yield(); LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? color : alternateColor; } long long numbers[] = { 0b0000000111111111111111111111111111111111111111111, //0 0b1111111000000000000000000000000000011111110000000, //1 0b0000000111111111111110000000111111111111111111111, //2 0b1111111111111100000000000000111111111111111111111, //3 0b1111111000000000000001111111000000011111111111111, //4 0b1111111111111100000001111111111111100000001111111, //5 0b1111111111111111111111111111111111100000001111111, //6 0b1111111000000000000000000000111111111111110000000, //7 0b1111111111111111111111111111111111111111111111111, //8 0b1111111000000000000001111111111111111111111111111, //9 0b0000000000000000000000000000000000000000000000000, //10 off 0b0000000000000000000001111111111111111111111111111, //degrees symbol 0b0000000111111111111111111111111111100000000000000, //C 0b0000000000000011111111111111111111100000001111111, //F }; Any ideas?
Hi @MacGyverr im not 100% sure I would need to try it… You could possibly use a float?
@MacGyverr @niall-cooley You can't use float or double as the numbers array essentially holds a bitmap of which LEDs should be lit or not for each digit.
Why will long long
not work? it should be 64 bits, which is enough to hold the required 49-bit bitmap? (I haven't actually tried more than 3 LEDs per segment).
@MacGyverr @niall-cooley You can't use float or double as the numbers array essentially holds a bitmap of which LEDs should be lit or not for each digit.
Why will
long long
not work? it should be 64 bits, which is enough to hold the required 49-bit bitmap? (I haven't actually tried more than 3 LEDs per segment).
@helpquick your completely right I didn’t think on it like that! Just an update with help from your comments above I got 2 per segment working perfectly 😊 ![Uploading 0206B1BD-874F-4C83-B346-B5FC2F80FC94.jpeg…]()
It starts to do weird things above 32 per segment, like never turning off certain lights and turning on less than the number it should, and if I use long long, the 32nd or 33rd light stays out all down the strip and it doesn't work right. This array method looks promising: byte digits[12][28] = {{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 0 {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1}, // Digit 1 {1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0}, // Digit 2 {1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1}, // Digit 3 {1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1}, // Digit 4 {1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1}, // Digit 5 {1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 6 {0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1}, // Digit 7 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 8 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1}, // Digit 9 | 2D Array for numbers on 7 segment {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, // Digit *0 {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0}}; // Digit C and then for(int k=0; k<=27;k++){ // Serial.print(digits[digit][k]); if (digits[digit][k]== 1){leds[cursor]=ledColor;} else if (digits[digit][k]==0){leds[cursor]=0x000000;}; cursor ++; }; But my complete lack of programming skills and my inability to fix a simple size issue, makes me think I'll never be able to convert Leon's superior web-server based code into using that either. :)
Alternative option would be to have the numbers[] array be just 1 bit per segment, then add an extra for loop to expand it to the number of LEDs
// bitmap for LEDs
byte numbers[] = {
// 7654321
0b0111111, // [0] 0
0b0100001, // [1] 1
0b1110110, // [2] 2
0b1110011, // [3] 3
0b1101001, // [4] 4
0b1011011, // [5] 5
0b1011111, // [6] 6
0b0110001, // [7] 7
0b1111111, // [8] 8
0b1111011, // [9] 9
0b0000000, // [10] off
0b1111000, // [11] degrees symbol
0b0011110, // [12] C(elsius)
0b1011100, // [13] F(ahrenheit)
};
then:
in the displayNumber
function:
for (byte i=0; i<7; i++){ // 7 segments
for (byte j=0; j<7; j++ { // 7 LEDs per segment
yield();
LEDs[i * 7 + j + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? color : alternateColor;
}
}
This is just an idea, I've not tested it. [edited] need to multiply i by the number of LEDs per segment
That worked perfectly, I don't know why I didn't think to do that in the first place, it is so simple but so clever and best I can tell, doesn't cause any extra flickering or anything. Thank you so much, you saved me soooooo much unnecessary work. :)
In case anyone is interested, I have uploaded an improved version of the code here: 7-Segment-WiFi-Clock
I am still working on improvements, but as it stands, number of LEDs per segment can be configured, WiFi uses AutoConnect captive portal, so no need for hard-coded SSID / PSK, and time will update from NTP.
Dear Leon,
I tried to make it by increasing the number of LEDs / Strips, from 3 LEDs to 5 LEDs.
But when you turn it on, many of the leds don't light up. The following sketch that I changed.
Please provide solutions and directions, so that it can be perfect.
Thank you.
include
include // Include RTC library by Makuna: https://github.com/Makuna/Rtc
include
include
include
include
include // Please read the instructions on http://arduino.esp8266.com/Arduino/versions/2.3.0/doc/filesystem.html#uploading-files-to-file-system
define countof(a) (sizeof(a) / sizeof(a[0]))
define NUM_LEDS 142 // Total of 142 LED's ////5 led per segment X 7 segment X 4 digit + 2 dot titik
define DATA_PIN D6 // Change this if you are using another type of ESP board than a WeMos D1 Mini
define MILLI_AMPS 4000 // asumsi 800mA jika 1ed per segment maka 5 ledper segment 4.000mA
define COUNTDOWN_OUTPUT D5 // COUNTDOWN_OUTPUT D5 to buzzer 3 beeps when the countdown timer is reached
define WIFIMODE 2 // 0 = Only Soft Access Point, 1 = Only connect to local WiFi network with UN/PW, 2 = Both
if defined(WIFIMODE) && (WIFIMODE == 0 || WIFIMODE == 2)
const char APssid = "7Segment-5Led";
const char APpassword = "1234567890";
endif
if defined(WIFIMODE) && (WIFIMODE == 1 || WIFIMODE == 2)
include "Credentials.h" // Create this file in the same directory as the .ino file and add your credentials (#define SID YOURSSID and on the second line #define PW YOURPASSWORD)
const char ssid = SID; const char password = PW;
endif
RtcDS3231 Rtc(Wire);
ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdateServer;
CRGB LEDs[NUM_LEDS];
// Settings unsigned long prevTime = 0; byte r_val = 255; byte g_val = 0; byte b_val = 0; bool dotsOn = true; byte brightness = 255; float temperatureCorrection = -3.0; byte temperatureSymbol = 12; // 12=Celcius, 13=Fahrenheit check 'numbers' byte clockMode = 0; // Clock modes: 0=Clock, 1=Countdown, 2=Temperature, 3=Scoreboard unsigned long countdownMilliSeconds; unsigned long endCountDownMillis; byte hourFormat = 24; // Change this to 12 if you want default 12 hours format instead of 24
CRGB countdownColor = CRGB::Green; byte scoreboardLeft = 0; byte scoreboardRight = 0; CRGB scoreboardColorLeft = CRGB::Green; CRGB scoreboardColorRight = CRGB::Red; CRGB alternateColor = CRGB::Black; long numbers[] = { 0b00000111111111111111111111111111111, // [0] 0 ////5 led per segment 0b00000111110000000000000000000011111, // [1] 1 ////5 led per segment 0b11111111111111100000111111111100000, // [2] 2 ////5 led per segment 0b11111111111111100000000001111111111, // [3] 3 ////5 led per segment 0b11111111110000011111000000000011111, // [4] 4 ////5 led per segment 0b11111000001111111111000001111111111, // [5] 5 ////5 led per segment 0b11111000001111111111111111111111111, // [6] 6 ////5 led per segment 0b00000111111111100000000000000011111, // [7] 7 ////5 led per segment 0b11111111111111111111111111111111111, // [8] 8 ////5 led per segment 0b11111111111111111111000001111111111, // [9] 9 ////5 led per segment 0b00000000000000000000000000000000000, // [10] off ////5 led per segment 0b11111111111111111111000000000000000, // [11] degrees symbol ////5 led per segment 0b00000000001111111111111111111100000, // [12] C(elsius) ////5 led per segment 0b11111000001111111111111110000000000, // [13] F(ahrenheit) ////5 led per segment };
void setup() { pinMode(COUNTDOWN_OUTPUT, OUTPUT); Serial.begin(115200); delay(200);
// RTC DS3231 Setup Rtc.Begin();
RtcDateTime compiled = RtcDateTime(DATE, TIME);
if (!Rtc.IsDateTimeValid()) { if (Rtc.LastError() != 0) { // we have a communications error see https://www.arduino.cc/en/Reference/WireEndTransmission for what the number means Serial.print("RTC communications error = "); Serial.println(Rtc.LastError()); } else { // Common Causes: // 1) first time you ran and the device wasn't running yet // 2) the battery on the device is low or even missing Serial.println("RTC lost confidence in the DateTime!"); // following line sets the RTC to the date & time this sketch was compiled // it will also reset the valid flag internally unless the Rtc device is // having an issue Rtc.SetDateTime(compiled); } }
WiFi.setSleepMode(WIFI_NONE_SLEEP);
delay(200); //Serial.setDebugOutput(true);
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(LEDs, NUM_LEDS);
FastLED.setDither(false); FastLED.setCorrection(TypicalLEDStrip); FastLED.setMaxPowerInVoltsAndMilliamps(5, MILLI_AMPS); fill_solid(LEDs, NUM_LEDS, CRGB::Black); FastLED.show();
// WiFi - AP Mode or both
if defined(WIFIMODE) && (WIFIMODE == 0 || WIFIMODE == 2)
WiFi.mode(WIFI_AP_STA); WiFi.softAP(APssid, APpassword); // IP is usually 192.168.4.1 Serial.println(); Serial.print("SoftAP IP: "); Serial.println(WiFi.softAPIP());
endif
// WiFi - Local network Mode or both
if defined(WIFIMODE) && (WIFIMODE == 1 || WIFIMODE == 2)
byte count = 0; WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { // Stop if cannot connect if (count >= 60) { Serial.println("Could not connect to local WiFi.");
return; }
} Serial.print("Local IP: "); Serial.println(WiFi.localIP());
IPAddress ip = WiFi.localIP(); Serial.println(ip[3]);
endif
httpUpdateServer.setup(&server);
// Handlers server.on("/color", HTTP_POST, []() {
r_val = server.arg("r").toInt(); g_val = server.arg("g").toInt(); b_val = server.arg("b").toInt(); server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/setdate", HTTP_POST, []() { // Sample input: date = "Dec 06 2009", time = "12:34:56" // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec String datearg = server.arg("date"); String timearg = server.arg("time"); Serial.println(datearg); Serial.println(timearg);
char d[12]; char t[9]; datearg.toCharArray(d, 12); timearg.toCharArray(t, 9); RtcDateTime compiled = RtcDateTime(d, t); Rtc.SetDateTime(compiled);
clockMode = 0;
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/brightness", HTTP_POST, []() {
brightness = server.arg("brightness").toInt();
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/countdown", HTTP_POST, []() {
countdownMilliSeconds = server.arg("ms").toInt();
byte cd_r_val = server.arg("r").toInt(); byte cd_g_val = server.arg("g").toInt(); byte cd_b_val = server.arg("b").toInt(); digitalWrite(COUNTDOWN_OUTPUT, LOW); countdownColor = CRGB(cd_r_val, cd_g_val, cd_b_val); endCountDownMillis = millis() + countdownMilliSeconds; allBlank(); clockMode = 1;
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/temperature", HTTP_POST, []() {
temperatureCorrection = server.arg("correction").toInt(); temperatureSymbol = server.arg("symbol").toInt(); clockMode = 2;
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/scoreboard", HTTP_POST, []() {
scoreboardLeft = server.arg("left").toInt(); scoreboardRight = server.arg("right").toInt(); scoreboardColorLeft = CRGB(server.arg("rl").toInt(),server.arg("gl").toInt(),server.arg("bl").toInt()); scoreboardColorRight = CRGB(server.arg("rr").toInt(),server.arg("gr").toInt(),server.arg("br").toInt()); clockMode = 3;
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/hourformat", HTTP_POST, []() {
hourFormat = server.arg("hourformat").toInt(); clockMode = 0;
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
server.on("/clock", HTTP_POST, []() {
clockMode = 0;
server.send(200, "text/json", "{\"result\":\"ok\"}"); });
// Before uploading the files with the "ESP8266 Sketch Data Upload" tool, zip the files with the command "gzip -r ./data/" (on Windows I do this with a Git Bash) // *.gz files are automatically unpacked and served from your ESP (so you don't need to create a handler for each file). server.serveStatic("/", SPIFFS, "/", "max-age=86400"); server.begin();
SPIFFS.begin(); Serial.println("SPIFFS contents:"); Dir dir = SPIFFS.openDir("/"); while (dir.next()) { String fileName = dir.fileName(); size_t fileSize = dir.fileSize(); Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), String(fileSize).c_str()); } Serial.println();
digitalWrite(COUNTDOWN_OUTPUT, LOW); }
void loop(){
server.handleClient();
unsigned long currentMillis = millis();
if (currentMillis - prevTime >= 1000) { prevTime = currentMillis;
}
}
void displayNumber(byte number, byte segment, CRGB color) { /*
12 13 14
11 15 10 16 /71 __ _9 17 141 34 19 18 //////////KETERANGAN BISA DILIHAT DI KONFIGURASI LED 5 PIXEL.JPG
/107 /72 /70 /35 8 /0 _7 _1 _6 _2 _5 _4 _3
*/
// segment from left to right: 3, 2, 1, 0 byte startindex = 0; switch (segment) { case 0: startindex = 0; //// value start index digit 1 led no 0. break; case 1: startindex = 35; //// value start index digit 2 led no 35. break; case 2: startindex = 72; //// value start index digit 3 led no 72. break; case 3: startindex = 107; //// value start index digit 4 led no 107. break;
}
for (byte i=0; i<35; i++){ //// value start index digit 2 led no 35. yield(); LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? color : alternateColor; } }
void allBlank() { for (int i=0; i<NUM_LEDS; i++) { LEDs[i] = CRGB::Black; } FastLED.show(); }
void updateClock() {
RtcDateTime now = Rtc.GetDateTime(); // printDateTime(now);
int hour = now.Hour(); int mins = now.Minute(); int secs = now.Second();
if (hourFormat == 12 && hour > 12) hour = hour - 12;
byte h1 = hour / 10; byte h2 = hour % 10; byte m1 = mins / 10; byte m2 = mins % 10;
byte s1 = secs / 10; byte s2 = secs % 10;
CRGB color = CRGB(r_val, g_val, b_val);
if (h1 > 0) displayNumber(h1,3,color); else displayNumber(10,3,color); // Blank
displayNumber(h2,2,color); displayNumber(m1,1,color); displayNumber(m2,0,color);
displayDots(color);
}
void updateCountdown() {
if (countdownMilliSeconds == 0 && endCountDownMillis == 0) return;
unsigned long restMillis = endCountDownMillis - millis(); unsigned long hours = ((restMillis / 1000) / 60) / 60; unsigned long minutes = (restMillis / 1000) / 60; unsigned long seconds = restMillis / 1000; int remSeconds = seconds - (minutes 60); int remMinutes = minutes - (hours 60);
Serial.print(restMillis); Serial.print(" "); Serial.print(hours); Serial.print(" "); Serial.print(minutes); Serial.print(" "); Serial.print(seconds); Serial.print(" | "); Serial.print(remMinutes); Serial.print(" "); Serial.println(remSeconds);
byte h1 = hours / 10; byte h2 = hours % 10; byte m1 = remMinutes / 10; byte m2 = remMinutes % 10;
byte s1 = remSeconds / 10; byte s2 = remSeconds % 10;
CRGB color = countdownColor; if (restMillis <= 60000) { color = CRGB::Red; }
if (hours > 0) { // hh:mm displayNumber(h1,3,color); displayNumber(h2,2,color); displayNumber(m1,1,color); displayNumber(m2,0,color);
} else { // mm:ss
displayNumber(m1,3,color); displayNumber(m2,2,color); displayNumber(s1,1,color); displayNumber(s2,0,color);
}
displayDots(color);
if (hours <= 0 && remMinutes <= 0 && remSeconds <= 0) { Serial.println("Countdown timer ended."); //endCountdown(); countdownMilliSeconds = 0; endCountDownMillis = 0; digitalWrite(COUNTDOWN_OUTPUT, HIGH); delay(500); digitalWrite(COUNTDOWN_OUTPUT,LOW); delay(500); digitalWrite(COUNTDOWN_OUTPUT, HIGH); delay(500); digitalWrite(COUNTDOWN_OUTPUT,LOW); delay(500); digitalWrite(COUNTDOWN_OUTPUT, HIGH); delay(500); digitalWrite(COUNTDOWN_OUTPUT,LOW); delay(500); return; }
}
void endCountdown() { allBlank(); for (int i=0; i<NUM_LEDS; i++) { if (i>0) LEDs[i-1] = CRGB::Black;
}
}
void displayDots(CRGB color) { if (dotsOn) { LEDs[70] = color; //// value dot 5 segment per led LEDs[71] = color; //// value dot 5 segment per led } else { LEDs[70] = CRGB::Black; //// value dot 5 segment per led LEDs[71] = CRGB::Black; //// value dot 5 segment per led }
dotsOn = !dotsOn;
}
void hideDots() { LEDs[70] = CRGB::Black; //// value dot 5 segment per led LEDs[71] = CRGB::Black; //// value dot 5 segment per led }
void updateTemperature() { RtcTemperature temp = Rtc.GetTemperature(); float ftemp = temp.AsFloatDegC(); float ctemp = ftemp + temperatureCorrection; Serial.print("Sensor temp: "); Serial.print(ftemp); Serial.print(" Corrected: "); Serial.println(ctemp);
if (temperatureSymbol == 13) ctemp = (ctemp * 1.8000) + 32;
byte t1 = int(ctemp) / 10; byte t2 = int(ctemp) % 10; CRGB color = CRGB(r_val, g_val, b_val); displayNumber(t1,3,color); displayNumber(t2,2,color); displayNumber(11,1,color); displayNumber(temperatureSymbol,0,color); hideDots(); }
void updateScoreboard() { byte sl1 = scoreboardLeft / 10; byte sl2 = scoreboardLeft % 10; byte sr1 = scoreboardRight / 10; byte sr2 = scoreboardRight % 10;
displayNumber(sl1,3,scoreboardColorLeft); displayNumber(sl2,2,scoreboardColorLeft); displayNumber(sr1,1,scoreboardColorRight); displayNumber(sr2,0,scoreboardColorRight); hideDots(); }
void printDateTime(const RtcDateTime& dt) { char datestring[20];
}