und der Stoppuhr-Slave (komplettes Programm):
/*
-WS2811 (5V- 144LED/m)
-4 WS2811-Outputs (Min:Sec:Fractions und dots)
-RS485-Module
-Serial commandos are bytes (START = 20, STOP = 22, RESET = 24)
*/
#include <SoftwareSerial.h>
SoftwareSerial ClockSerial(8, 9); // RX, TX
#define enablePin 10
byte readcommand;
#include <Adafruit_NeoPixel.h>
#define fraPin 6 // fractions
#define secPin 5 // sekunden
#define minPin 4 // minuten
#define dotPin 3 // Punkte
Adafruit_NeoPixel SEGfra = Adafruit_NeoPixel(98, fraPin, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel SEGsec = Adafruit_NeoPixel(98, secPin, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel SEGmin = Adafruit_NeoPixel(98, minPin, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel SEGdot = Adafruit_NeoPixel( 8, dotPin, NEO_GRB + NEO_KHZ800);
byte digits[10][7] = {{0,1,1,1,1,1,1}, // Digit 0
{0,1,0,0,0,0,1}, // Digit 1
{1,1,1,0,1,1,0}, // Digit 2
{1,1,1,0,0,1,1}, // Digit 3
{1,1,0,1,0,0,1}, // Digit 4
{1,0,1,1,0,1,1}, // Digit 5
{1,0,1,1,1,1,1}, // Digit 6
{0,1,1,0,0,0,1}, // Digit 7
{1,1,1,1,1,1,1}, // Digit 8
{1,1,1,1,0,1,1}}; // Digit 9 | 2D Array for numbers on 7 segment
uint32_t colour;
unsigned long number, lastnumber, fractimer, starttime, stoptime;
long minutes, seconds;
float fractions = 0;
float calval = 5;
int timecal = 7875; // Calibration-Variable for calval/100 sec
int debouncer, val, index, dots;
boolean blinking, lastblinking, buttonstate, lastbuttonstate, dot;
byte lasthunderttausender, lastzehntausender, lasttausender, lasthunderter, lastzehner, lasteiner;
void setup() {
ClockSerial.begin(9600); // initialize serial at baudrate 9600
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW); // (Pin EN always LOW to receive value from Master)
SEGfra.begin();
SEGfra.show(); // Initialize all pixels to 'off'
SEGsec.begin();
SEGsec.show(); // Initialize all pixels to 'off'
SEGmin.begin();
SEGmin.show(); // Initialize all pixels to 'off'
SEGdot.begin();
SEGdot.show();
//Serial.begin(9600);
Serial.println("ready");
blinking = false;
number = 0;
lastnumber = 888888;
fractions = 0;
minutes = 0;
seconds = 0;
val=2;
stoptime = millis();
delay(500);
lasthunderttausender = 99;
lastzehntausender = 99;
lasttausender = 99;
lasthunderter = 99;
lastzehner = 99;
lasteiner = 99;
}
void loop() {
if (blinking == true) { checkTime(); }
checkSerial();
if ((number != lastnumber) || (blinking != lastblinking)) { ShowDigits(number, Wheel(val)); }
lastnumber = number;
lastblinking = blinking;
}
void checkSerial() {
if (ClockSerial.available()) {
delay(1);
while (ClockSerial.available()) {
readcommand = ClockSerial.read(); // Receive byte from Master
delay(1);
if (readcommand == 22) { break; }
}
switch (readcommand) {
case 20:
// CLOCK START
fractimer = micros(); // START FRACTIONS-TIMER
starttime = millis();
blinking = true;
val=88; // grün
break;
case 22:
// CLOCK STOP
stoptime = millis();
blinking = false;
val=2; //rot
break;
case 24:
// RESET
blinking = false;
number = 0; minutes = 0; seconds = 0; fractions = 0;
lasthunderttausender = 99; lastzehntausender = 99; lasttausender = 99; lasthunderter = 99; lastzehner = 99; lasteiner = 99;
lastnumber = 888888;
val=2;
BlackOut();
break;
}
}
}
void checkTime() {
while ((micros()-fractimer) > timecal) {
// calval/100 Sek vergangen:
fractions++;
if (fractions > 99) { fractions = fractions - 100; seconds++; }
if (seconds > 59) { seconds = 0; minutes++; }
if ((minutes > 98) && (seconds > 58) && (fractions > 98)) { blinking = false; }
number = (fractions + (seconds * 100) + (minutes*10000));
//fractimer = micros();
fractimer = fractimer + timecal;
}
}
void ShowDigits(long Zahl, uint32_t Farbe) {
byte einer = Zahl % 10;
byte zehner = (Zahl / 10) % 10;
byte hunderter = (Zahl / 100) % 10;
byte tausender = (Zahl / 1000) % 10;
byte zehntausender = (Zahl / 10000) % 10;
byte hunderttausender = (Zahl / 100000) % 10;
boolean showsegment = false;
for(index = 0; index < 7; index++) {
//Segment-Minuten
if ((lasthunderttausender != hunderttausender) || (lastblinking != blinking)) {
showsegment = true;
if (digits[hunderttausender][index] == 0) {colour = 0;}
else {colour = Farbe;}
for (int dots = 0; dots < 7; dots++) { SEGmin.setPixelColor((index*7)+(49*0)+dots, colour); }
}
if ((lastzehntausender != zehntausender) || (lastblinking != blinking)) {
showsegment = true;
if (digits[zehntausender][index] == 0) {colour = 0;}
else {colour = Farbe;}
for (int dots = 0; dots < 7; dots++) { SEGmin.setPixelColor((index*7)+(49*1)+dots, colour); }
}
}
if (showsegment == true) {
SEGmin.show();
showsegment = false;
lasthunderttausender = hunderttausender;
lastzehntausender = zehntausender;
}
//Segment-Sekunden
for(index = 0; index < 7; index++) {
if ((lasttausender != tausender) || (lastblinking != blinking)) {
showsegment = true;
if (digits[tausender][index] == 0) {colour = 0;}
else {colour = Farbe;}
for (int dots = 0; dots < 7; dots++) { SEGsec.setPixelColor((index*7)+(49*0)+dots, colour); }
}
if ((lasthunderter != hunderter) || (lastblinking != blinking)) {
showsegment = true;
if (digits[hunderter][index] == 0) {colour = 0;}
else {colour = Farbe;}
for (int dots = 0; dots < 7; dots++) { SEGsec.setPixelColor((index*7)+(49*1)+dots, colour); }
}
}
if (showsegment == true) {
SEGsec.show();
showsegment = false;
lasttausender = tausender;
lasthunderter = hunderter;
}
//Segment-Hundertstel
for(index = 0; index < 7; index++) {
if ((lastzehner != zehner) || (lastblinking != blinking)) {
showsegment = true;
if (digits[zehner][index] == 0) {colour = 0;}
else {colour = Farbe;}
for (int dots = 0; dots < 7; dots++) { SEGfra.setPixelColor((index*7)+(49*0)+dots, colour); }
}
if ((lasteiner != einer) || (lastblinking != blinking)) {
showsegment = true;
if (digits[einer][index] == 0) {colour = 0;}
else {colour = Farbe;}
for (int dots = 0; dots < 7; dots++) { SEGfra.setPixelColor((index*7)+(49*1)+dots, colour); }
}
}
if (showsegment == true) {
SEGfra.show();
showsegment = false;
lastzehner = zehner;
lasteiner = einer;
}
for (dots = 0; dots < 4; dots++) {
SEGdot.setPixelColor(dots, Farbe); // Punkte Min:Sec
if ((zehner < 5) || (blinking == false)) { SEGdot.setPixelColor((4+dots), Farbe); }
else { SEGdot.setPixelColor((4+dots), 0); }
}
SEGdot.show();
}
void BlackOut() {
for (int dark = 0; dark < SEGmin.numPixels() ; dark++) {
SEGfra.setPixelColor(dark, 0);
SEGsec.setPixelColor(dark, 0);
SEGmin.setPixelColor(dark, 0);
if (dark < 8) { SEGdot.setPixelColor(dark, 0); }
}
SEGfra.show();
SEGsec.show();
SEGmin.show();
SEGdot.show();
lasthunderttausender = 99; lastzehntausender = 99; lasttausender = 99; lasthunderter = 99; lastzehner = 99; lasteiner = 99;
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return SEGmin.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return SEGmin.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return SEGmin.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
Sende oder empfange ich die Daten fachlich falsch?
Sollte ich an der Baudrate etwas verändern?
"Vergewaltige" ich den Serial Buffer mit dem häufigen Senden?
Sollte ich beim Senden/Empfangen mit anderem timing (bestimmte delays) arbeiten?
Da das Problem auch nur auftritt, wenn "die Uhr läuft", sprich: wenn der Arduino sehr mit der recht intensiven Arbeit der Aktualisierung aller Neopixel beschäftigt ist. Könnte da das Problem der "überhörten" Kommandos liegen?
Eine ganz andere Lösung bei gleichem Hardware-Aufbau?
Bin für Rückfragen und ... Inspirationen offen 