Led klok project, probleem met keuze knop.

Hallo,

ik heb een klok gemaakt met ws2801 led strip, arduino nano, en een ds1307 rtc clip.
de klok werkt prima, alleen heb ik een knop toegevoegd die je laat kiezen tussen de verschillende uitvoeringen.

regenboog met witte wijzers
wijzers alleen in blauw (seconde), rood (minuten), groen (uren)
volledig wit met rode wijzers.
regenboog die tegen de klok in draait (void rotrainbow() ) met witte wijzers.

die laatste is het probleem.
ik heb een void animatiemode() die de selectie van de uitvoeringen regeld.
die werkt prima zolang ik optie 4 maar uitzet.
je kan door de modes heen zappen tot je bij 4 komt.
enige manier om weer bij klok type 1 te komen is de nano te resetten.
zet ik // voor optie 4 gaat ie naar 5x drukken weer terug naar 1

de code is bij elkaar gekopieerd en geplakt en hier een daar wat aangepast
zodat het werkt. misschien niet de beste manier maar ok doet dit ook nog
niet zo lang.

hoop dat iemand een idee heeft waarom dit niet werkt?
(de settime is hier verwijderd ivm te veel karakters in de post)

hier de code:

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

#define NUM_LEDS 60

const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int hourButtonPin = 6;
const int minButtonPin = 7;

int buttonPushCounter = 1;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
int hourButtonState;
int minButtonState;

int seconds; //00-59;
int minutes; //00-59;
int hours;//1-12 - 00-23;
int day;//1-7
int date;//01-31
int month;//01-12
int year;//0-99;

CRGB leds[NUM_LEDS];
RTC_DS1307 rtc;

void setup() {
   Serial.begin(57600);
   pinMode(buttonPin, INPUT);
   pinMode(hourButtonPin,INPUT);
   pinMode(minButtonPin,INPUT);
   hourButtonState = 0;
   minButtonState = 0;
   
   #ifdef AVR
   Wire.begin();
   #else
   Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
   #endif
   rtc.begin();
   if (! rtc.isrunning()) {
   Serial.println("RTC is NOT running!");
   }
   
   FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS);

}
void loop() {
  animationmode();
  check_buttons();
}

void animationmode(){
  
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
        if (buttonState == HIGH) {
        buttonPushCounter++;
       Serial.println(buttonPushCounter);
    }
    else {
      }
  }
   lastButtonState = buttonState;

  if (buttonPushCounter == 1) {  
      rainbow();
  }
  if (buttonPushCounter == 2){ 
      rgbclock();
  }
  if (buttonPushCounter == 3) {
      ringred();
  } 
  if (buttonPushCounter == 4) { //het probleem kind
      rotrainbow();                    // na uit zetten (// er voor) werkt het prima
  } 
  if (buttonPushCounter == 5){  
      buttonPushCounter = 1;
  }
 
}


void rainbow(){
    DateTime now = rtc.now();
    
    fill_rainbow( leds, NUM_LEDS, 0, 4.25);
    leds[(now.second())%60] = CRGB::White;
    leds[(now.minute())%60] = CRGB::White; 
     if (now.minute()== 0) {
    leds[((59)%60)] = CRGB::White;
    }
    else {
    leds[((now.minute()-1)%60)] = CRGB::White;
    } 
    unsigned char hourpos = (now.hour()%12)*5;
    if (now.minute() > 47) {
    leds[((59+hourpos+4)%60)%60] = CRGB::White;
    leds[(hourpos+4)%60] = CRGB::White;
    leds[((hourpos+1+4))%60] = CRGB::White; 
    }
    else if (now.minute() > 35) {
    leds[((59+hourpos+3)%60)%60] = CRGB::White;
    leds[(hourpos+3)%60] = CRGB::White;
    leds[((hourpos+1+3))%60] = CRGB::White; 
    }
    else if (now.minute()  > 23) {
    leds[((59+hourpos+2)%60)%60] = CRGB::White;
    leds[(hourpos+2)%60] = CRGB::White;
    leds[((hourpos+1+2))%60] = CRGB::White; 
    }
    else if (now.minute()  > 11) {
    leds[((59+hourpos+1)%60)%60] = CRGB::White;
    leds[(hourpos+1)%60] = CRGB::White;
    leds[((hourpos+1+1))%60] = CRGB::White; 
    }
    else {
    leds[((59+hourpos)%60)%60] = CRGB::White;
    leds[(hourpos)%60] = CRGB::White;
    leds[((hourpos+1))%60] = CRGB::White; 
    } 
    FastLED.show();
    delay(50);
}

void rgbclock(){
   DateTime now = rtc.now();
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    memset(leds, 0, NUM_LEDS * 3);
    leds[(now.second())%60] = CRGB::Blue;
   leds[(now.minute())%60] = CRGB::Red; 
     if (now.minute()== 0) {
    leds[((59)%60)] = CRGB::Red;
    }
    else {
    leds[((now.minute()-1)%60)] = CRGB::Red;
    } 
    unsigned char hourpos = (now.hour()%12)*5;
        if (now.minute() > 47) {
    leds[((59+hourpos+4)%60)%60] = CRGB::Green;
    leds[(hourpos+4)%60] = CRGB::Green;
    leds[((hourpos+1+4))%60] = CRGB::Green; 
    }
    else if (now.minute() > 35) {
    leds[((59+hourpos+3)%60)%60] = CRGB::Green;
    leds[(hourpos+3)%60] = CRGB::Green;
    leds[((hourpos+1+3))%60] = CRGB::Green; 
    }
    else if (now.minute()  > 23) {
    leds[((59+hourpos+2)%60)%60] = CRGB::Green;
    leds[(hourpos+2)%60] = CRGB::Green;
    leds[((hourpos+1+2))%60] = CRGB::Green; 
    }
    else if (now.minute()  > 11) {
    leds[((59+hourpos+1)%60)%60] = CRGB::Green;
    leds[(hourpos+1)%60] = CRGB::Green;
    leds[((hourpos+1+1))%60] = CRGB::Green; 
    }
    else {
    leds[((59+hourpos)%60)%60] = CRGB::Green;
    leds[(hourpos)%60] = CRGB::Green;
    leds[((hourpos+1))%60] = CRGB::Green; 
    }
    FastLED.show();
}
 
void ringred() {
    DateTime now = rtc.now(); 
    memset(leds, 255, NUM_LEDS * 3);
    leds[(now.second())%60] = CRGB::Red;
    leds[(now.minute())%60] = CRGB::Red; 
     if (now.minute()== 0) {
    leds[((59)%60)] = CRGB::Red;
    }
    else {
    leds[((now.minute()-1)%60)] = CRGB::Red;
    }
    unsigned char hourpos = (now.hour()%12)*5;
    if (now.minute() > 47) {
    leds[((59+hourpos+4)%60)%60] = CRGB::Red;
    leds[(hourpos+4)%60] = CRGB::Red;
    leds[((hourpos+1+4))%60] = CRGB::Red; 
    }
    else if (now.minute() > 35) {
    leds[((59+hourpos+3)%60)%60] = CRGB::Red;
    leds[(hourpos+3)%60] = CRGB::Red;
    leds[((hourpos+1+3))%60] = CRGB::Red; 
    }
    else if (now.minute()  > 23) {
    leds[((59+hourpos+2)%60)%60] = CRGB::Red;
    leds[(hourpos+2)%60] = CRGB::Red;
    leds[((hourpos+1+2))%60] = CRGB::Red; 
    }
    else if (now.minute()  > 11) {
    leds[((59+hourpos+1)%60)%60] = CRGB::Red;
    leds[(hourpos+1)%60] = CRGB::Red;
    leds[((hourpos+1+1))%60] = CRGB::Red; 
    }
    else {
    leds[((59+hourpos)%60)%60] = CRGB::Red;
    leds[(hourpos)%60] = CRGB::Red;
    leds[((hourpos+1))%60] = CRGB::Red; 
    }
    FastLED.show();
    delay(50);
}

void rotrainbow() {   // probleem kind
    
    
    for (int j=0; j <= 255; j++){
    fill_rainbow( leds, NUM_LEDS, (0, j), 4.25);
    
    DateTime now = rtc.now();
    leds[(now.second())%60] = CRGB::White;
    leds[(now.minute())%60] = CRGB::White; 
    if (now.minute()== 0) {
    leds[((59)%60)] = CRGB::White;
    }
    else {
    leds[((now.minute()-1)%60)] = CRGB::White;
    }
    unsigned char hourpos = (now.hour()%12)*5;
    if (now.minute() > 47) {
    leds[((59+hourpos+4)%60)%60] = CRGB::White;
    leds[(hourpos+4)%60] = CRGB::White;
    leds[((hourpos+1+4))%60] = CRGB::White; 
    }
    else if (now.minute() > 35) {
    leds[((59+hourpos+3)%60)%60] = CRGB::White;
    leds[(hourpos+3)%60] = CRGB::White;
    leds[((hourpos+1+3))%60] = CRGB::White; 
    }
    else if (now.minute()  > 23) {
    leds[((59+hourpos+2)%60)%60] = CRGB::White;
    leds[(hourpos+2)%60] = CRGB::White;
    leds[((hourpos+1+2))%60] = CRGB::White; 
    }
    else if (now.minute()  > 11) {
    leds[((59+hourpos+1)%60)%60] = CRGB::White;
    leds[(hourpos+1)%60] = CRGB::White;
    leds[((hourpos+1+1))%60] = CRGB::White; 
    }
    else {
    leds[((59+hourpos)%60)%60] = CRGB::White;
    leds[(hourpos)%60] = CRGB::White;
    leds[((hourpos+1))%60] = CRGB::White; 
    }
    delay(200);
    FastLED.show();
    }
}

Ik zou die index waardes in die functie eens uitprinten op Serial. Mogelijk zit je voorbij de maximale waarde van de Array.

DiSrUpTeR, je weet toch dat die void rotrainbow zo'n 51 seconden zal duren, he...

void rotrainbow() {   // probleem kind
    for (int j=0; j <= 255; j++){
    fill_rainbow( leds, NUM_LEDS, (0, j), 4.25);
    .
    .
    .
    .
    delay(200);
    FastLED.show();
    }
}

255 x 200 ms = 51 s
Maar goed, misschien heb je die delay daar enkel gezet tijdens het debuggen, en is het de bedoeling dat je die later nog weghaalt?

Wat ik wel erg raar vind, is de derde parameter voor de fill_rainbow routine: (0, j)
Diezelfde routine gebruik je ook in void rainbow(), maar daar is de derde parameter gewoon 0.

fill_rainbow( leds, NUM_LEDS, 0, 4.25);

Ik ken die fill_rainbow routine niet, en ik weet ok niet waar de parameters voor dienen. Maar de ene keer (0, j) en de andere keer 0 meegeven, lijkt mij niet juist...

ik denk dat Janosik iets op het spoor is.

fill_rainbow( leds, NUM_LEDS, (0, j), 4.25);

fill_rainbow vind je terug in het deel van de FastLED library : hsv2rgb

void fill_rainbow( struct CRGB * pFirstLED, int numToFill,
uint8_t initialhue,
uint8_t deltahue )

Ik denk niet dat je voor "uint8_t initialhue", de uitdrukking (0,j) kunt gebruiken.
misschien moet je daar gewoon j neerzetten.

dus: fill_rainbow( leds, NUM_LEDS, j, 4.25);

probeer dat eens, misschien helpt het wel.

cartoonist:
ik denk dat Janosik iets op het spoor is.

fill_rainbow( leds, NUM_LEDS, (0, j), 4.25);

fill_rainbow vind je terug in het deel van de FastLED library : hsv2rgb

void fill_rainbow( struct CRGB * pFirstLED, int numToFill,
uint8_t initialhue,
uint8_t deltahue )

Ik denk niet dat je voor "uint8_t initialhue", de uitdrukking (0,j) kunt gebruiken.
misschien moet je daar gewoon j neerzetten.

dus: fill_rainbow( leds, NUM_LEDS, j, 4.25);

probeer dat eens, misschien helpt het wel.

Dit gaat toevallig goed...... hier wordt gewoon de waarde j door gegeven. Je kunt het voor jezelf testen met de volgende code:

void setup() {
	Serial.begin(9600);
	Serial.println((0,5));
}
void loop(){

}

En compiler technisch gaat het "toevallig" ook goed.

@edit: ik zat nog ff te kijken, maar wordt dat uren formaat niet teruggegeven in 24-uurs ipv 12 uurs? En dan zit je volgens mij aardig buiten de ledstrip array te pielen....

@ Janosik.

die delay is om de rotatie/verschuiven van de rainbow te vertragen.
anders draaid ie als een gek rond en das beetje irritant aan de muur.

de regel fill_rainbow routine: (0, j) normaal staat daar een waarde van 0 > led nummer nul.
dat is het begin van het spectrum het verschil in kleur per led is de waarde op het eind 4,25 (255/60)
omdat met de waarde j start de rainbow steeds een ledje verder waardoor het lijkt dat hij rond draaid.

het enige verschil met de "gewone" rainbow is de regel for (int j=0; j <= 255; j++).
dacht dat het daar misschien de mist in gaat.
maar geen idee waarom.

@ cartoonist

gaat ik van avond ff proberen de 0 weg halen

laat weten wat het doet

zal vanavond de hele .ino bestand online zetten

Ik blijf het raar vinden, maar nico heeft gelijk: die derde parameter is zeker niet de oorzaak.

void setup(){
  Serial.begin(9600);
  Serial.println("*** 5 ***");
  test(5);
  Serial.println();
  Serial.println("*** (0,5) ***");
  test((0,5));
}

void loop(){
  
}

void test(int getal){
  for(int i=1;i<=getal;i++){
    Serial.println(i);
  }
}

geeft als resultaat:

*** 5 ***
1
2
3
4
5

*** (0,5) ***
1
2
3
4
5

Ik begin te vermoeden dat het probleem toch in die 51 seconden zit waar ik het eerst over had...

Je void loop() bestaat op zich uit slechts twee routines:

  • de ene gaat kijken of er OP DAT MOMENT een knop ingedrukt is
  • de andere zorgt ervoor dat er gepast gereageerd wordt

MAAR!!! eens dat je in weergavemodus #4 zit, zal de knopcontrole slechts 1 keer om de 51 seconden uitgevoerd worden... Dat wil zeggen dat de knop ingedrukt moet zijn op het moment dat je terugkeert van rotrainbow() naar animationmode() naar loop() waar je dan naar check_buttons() gaat.

Probeer eens om de knop gewoonweg 51 seconden lang ingedrukt te houden als je van #4 naar #5 wil gaan...

Je bent me voor :slight_smile:
Ik heb ff hier het programma gedraaid.... En het programma op zich werkt perfect :grin: zij het dat hij wat laat reageert in routine 4. Daarnaast kom je nooit meer in routine 1 omdat bij waarde 5 je de teller op 1 zet en dan bij het indrukken van de knop gelijk naar 2 gaat.
Ik heb bijgaand ff eea aangepast en gelijk die ellelange delay eruit gesloopt. Geeft ook wel een gaaf effect. Verder nog een debounce erin en wat parameters. De pinnen zijn wel aangepast alsmede mijn ledstrip (ik gebruik de WS2812B).

Door die for de nek om te draaien reageert de knop weer gewoon.

test.ino (8.08 KB)

klinkt wel logisch... :slight_smile:
gaat op de todo/test lijst

te gek die code
alleen handmatig tijd instellen weer in plakken.

hoop te doen vanavond

mannen alvast bedankt

Mark

Nu ik mijn laatste bericht nog eens nalees, moet ik zeggen dat eea wel erg ongelukkig geformuleerd is...

Janosik:
Ik blijf het raar vinden, maar nico heeft gelijk

Gelijk het er zo staat, lijkt het wel alsof ik het raar vind dat nico gelijk heeft... :grinning:

Nico, laat het mij goed maken door te zeggen dat jou code er prachtig uit ziet! :wink:

Mijn code is het niet hoor. Ik heb alleen een paar regels veranderd.

ik gaat de aanpassingen van Nico toevoegen.

in de bijlage zit de complete code.
inclusief aanpassen van de tijd met 2 andere knopen.
zal asap versie met de aanpassingen plaatsen.

nogmaals bedankt

Mark

klok_4_prog_-_mode-_time_set.ino (7.44 KB)

aanpassingen ingevoerd en werkt prima.
heb wel de delay 200 weer aangezet, beetje te ADHD voor aan de muur.
de complete aangepaste code in de bijlage.

hij is nog niet af maar voor het idee:

klok_4_prog_-_mode-_time_set_nico_mod_v2.ino (9.83 KB)

Gaaf!!!!!!

Kun je misschien van beide versies een filmpje online zetten ?
Dus de normale en de ADHD variant, ben benieuwd..

zal van het weekend ff filmpje online zetten :slight_smile:

Hier de klok "gewoon" op filmpje zie je het niet echt.
maar de de kleuren (regenboog) draaid tegen de klok in

hier op mijn "test opstelling" de ADHD Modus

gaat hem niet worden aan de muur, vandaar die 200ms delay

Thumbs Up!!!!

knap project :wink: