Forum: Mikrocontroller und Digitale Elektronik Arduino: Menü mit switch-methode, mein Codeschnipsel dabei, bitte ansehen und meckern :P


von Ardu (Gast)


Lesenswert?

Hi,

ich versuche ein Display Menü zu basteln, nachdem ich  mir zich 
unterschiedliche Möglickeiten angesehen habe und mir keines richtig 
einleuchtete. Hab überlegt, dass es doch mit der switch methode gehen 
müsste, nun aber mittendrin frag ich mich, ob das zu "dirty" ist, obs 
überhaupt funktioniert und wie ich die Tasterfunktion mit rein bringe, 
sollen drei Taster dran, zwei Richtungen und Menü/Ok. Hier mal der 
bisherige Versuch.

Mfg
1
    //MENU
2
    switch (menu)
3
    {
4
      case mainPage: //Main page
5
6
        display.clearDisplay();
7
8
        //Display time
9
        display.setCursor(16, 1); //Position text cursor for time display
10
        if (t.hour < 10) {
11
          display.print(" "); //Add leading space if single-digit hour
12
        }
13
        display.print(t.hour); //Display retrieved hours
14
        display.print(":"); //Display hour-minute separator
15
        if (t.min < 10) {
16
          display.print("0"); //Add leading zero if single-digit minute
17
        }
18
        display.print(t.min); //Display retrieved minutes
19
        display.print(":"); //Display minute-seconds separator
20
        if (t.sec < 10) {
21
          display.print("0"); //Add leading zero for single-digit seconds
22
        }
23
        display.print(t.sec); //Display retrieved seconds
24
25
      break;
26
27
      case setup: //Main settings menu
28
29
        display.clearDisplay();
30
31
        display.setCursor(1, 1);
32
        display.print("    Setup    ");
33
        display.drawLine(1, 9, 82, 1);
34
35
        display.setCursor(1, 10);
36
        display.print("Timer/Clock");
37
38
        display.setCursor(1, 45);
39
        display.print("Back");
40
41
        //Submenu
42
        switch (submenu)
43
        {
44
          case timer_clock: //Timer/clock settings menu
45
46
            display.clearDisplay();
47
48
            //Display head
49
            display.setCursor(0, 0);
50
            display.print(" Timer/Clock  ");
51
            display.drawLine(1, 9, 82, 1);
52
53
            //Display alarm 1
54
            display.setCursor(0, 10);
55
            display.print("On:");
56
57
            display.setCursor(0, 19); //Position text cursor for alarm 1 display
58
            if (wake_HOUR_1 < 10) {
59
              display.print(" "); //Add leading space if single-digit hour
60
            }
61
            display.print(wake_HOUR_1); //Display retrieved wake hours
62
            display.print(":"); //Display hour-minute separator
63
            if (wake_MINUTE_1 < 10) {
64
              display.print("0"); //Add leading zero if single-digit minute
65
            }
66
            display.print(wake_MINUTE_1); //Display retrieved wake minutes
67
68
            //Display alarm 2
69
            display.setCursor(36, 10);
70
            display.print("Off:");
71
72
            display.setCursor(36, 19); //Position text cursor for alarm 2 display
73
            if (wake_HOUR_2 < 10) {
74
              display.print(" "); //Add leading space if single-digit hour
75
            }
76
            display.print(wake_HOUR_2);
77
            display.print(":"); //Display hour-minute separator
78
            if (wake_MINUTE_2 < 10) {
79
              display.print("0"); //Add leading zero if single-digit minute
80
            }
81
            display.print(wake_MINUTE_2); //Display retrieved minutes
82
83
            //Display time
84
            display.setCursor(0, 28);
85
            display.print("Set time:");
86
87
            display.setCursor(0, 37); //Position text cursor for time display
88
            if (t.hour < 10) {
89
              display.print(" "); //Add leading space if single-digit hour
90
            }
91
            display.print(t.hour); //Display retrieved hours
92
            display.print(":"); //Display hour-minute separator
93
            if (t.min < 10) {
94
              display.print("0"); //Add leading zero if single-digit minute
95
            }
96
            display.print(t.min); //Display retrieved minutes
97
            display.print(":"); //Display minute-seconds separator
98
            if (t.sec < 10) {
99
              display.print("0"); //Add leading zero for single-digit seconds
100
            }
101
            display.print(t.sec); //Display retrieved seconds
102
103
            display.setCursor(0, 46);
104
            display.print("Back");
105
106
          break;
107
        }
108
        break;
109
    }

von Ardu (Gast)


Lesenswert?

huhu :)

von Falk B. (falk)


Lesenswert?

@ Ardu (Gast)

>ich versuche ein Display Menü zu basteln, nachdem ich  mir zich
>unterschiedliche Möglickeiten angesehen habe und mir keines richtig
>einleuchtete. Hab überlegt, dass es doch mit der switch methode gehen
>müsste,

Kann man machen.

> nun aber mittendrin frag ich mich, ob das zu "dirty" ist,

Nein.

> obs
>überhaupt funktioniert

Man sollte KEIN display.clearDisplay(); machen, denn das flackert immer 
beim Neuaufbau. Deutlich besser und schneller ist ein ÜBERSCHREIBEN das 
aktuellen Displays, incl. Leerzeichen natürlich.

>und wie ich die Tasterfunktion mit rein bringe,
>sollen drei Taster dran, zwei Richtungen und Menü/Ok. Hier mal der
>bisherige Versuch.

Die Taster liest man per Timer und Entprellung in einem Interrupt ein, 
siehe Entprellung, der Codeschnipsel von Peter ist ja schon legendär 
;-)

https://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29

Dann gibt es eine Funktion, welche die Tasten ausliest. Damit geht man 
dann in den switch und reagiert entsprechend. Etwa so.

1
uint8_t key;
2
3
key = get_key_press( (1<<KEY1) | (1<<KEY2) | (1<<KEY3) )
4
5
switch (menu) {
6
  case mainPage:
7
    if (key & (1<<KEY1) ) {
8
      menu = setup;
9
    }
10
  break;

von Ardu (Gast)


Lesenswert?

Juhu, eine Antwort :D ...

Du meinst die Bereiche des alten Bildes mit Leerzeichen im neuen 
überschreiben?

Die Taster entprelle ich so:
1
  //Menu/set button open menu - outside time/display update processing for faster button response
2
  if (!digitalRead(8)) { //Read menu/set button
3
    delay(25); //25ms debounce time
4
    if (!digitalRead(8)) { //Activate setting mode change after 100ms button press
5
      menu = menu; //Increment the setting mode on each button press
6
      }
7
      while (!digitalRead(8)) {} //Wait for button release
8
    }
Naja, ich werds erstmal so versuchen...

Cool, so habe ich auch gedacht, die Taster-If's in die Switch-Ebenen 
einzubauen und darauf hoffen, dass sie dann entsprechen innerhalb der 
Switch-Ebenen funktionieren, d.h. dass der Menü-Button automatisch zum 
Ok-Button wird. Denke ich so richtig?

Vielen lieben Dank soweit, nur eine Antwort, aber absolut perfekt :)

von Ardu (Gast)


Lesenswert?

Guten Morgen :)

Mal kurz den Fred aufwärmen...

von Leuchte, die (Gast)


Lesenswert?

seehr wartbar, dieses eeeelllllenlaaaaange switch statement; aber sowas 
von.

Der Übersicht halber, sollte so eine Verzweigungsleiter doch +/- 
innerhalb 1 Bildschirmseite Platz finden, auch nach künftigen 
Erweiterungen.

Also vllt. Funktionen schreiben:
1
:
2
  switch(menuContext->wahl) {
3
  case MENU1: f_MENU1(menuContext); break;
4
  case MENU2: f_MENU2(menuContext); break;
5
  case MENU3: f_MENU3(menuContext); break;
6
  default: implVersemmelt(menuContext);
7
  }

  Der aufmerksame Codeleser sieht aber dass sowas nach Funktionstabellen 
riecht, usw...

von Falk B. (falk)


Lesenswert?

@Ardu (Gast)

>Du meinst die Bereiche des alten Bildes mit Leerzeichen im neuen
>überschreiben?

Ja.

>Die Taster entprelle ich so:

Nicht wirklich gut, vor allem weil du auf das Loslassen des Tasters 
wartest. Das ist unnötig und kontraproduktiv. Denn wenn der Anwender, 
warum auch immer, die Taste gedrückt hält, steht dein Programm!

Wichtig ist die logische Trennung von Tastenentprellung und 
Weiterverarbeitung in deiner Statemachine. Die ist in deinem 
Beispiel NICHT drin, das ist unbrauchbar. Wie es richtig geht habe ich 
dir schon gesagt.

Für den ersten schnellen Test kann man es so machen, später ist ein 
Timer DRINGEND zu empfehlen.
1
#define KEY_MENU_UP 1
2
#define KEY_MENU_DOWN 2
3
#define KEY_MENU_OK 4
4
#define KEY_MENU_ESCAPE 8
5
6
7
uint8_t get_key(void) {
8
  static uint8_t key_old;
9
  uint8_t key, press;
10
11
  key = 0;
12
13
  // sample multiple keys
14
  if (digital_read(8)) key |= KEY_MENU_UP;
15
  if (digital_read(9)) key |= KEY_MENU_DOWN;
16
  if (digital_read(10)) key |= KEY_MENU_OK;
17
  if (digital_read(11)) key |= KEY_MENU_ESCAPE;
18
19
  press = key & ~old_key;   // active edge of keys
20
  delay(10);   //10ms debounce time
21
  key_old = key;
22
  return press;
23
}
24
25
//....
26
27
menu_key = get_key();
28
29
if (menu_key & KEY_MENU_UP) { // mach was bei Taste MENU_UP
30
}
31
32
if (menu_key & KEY_MENU_OK) { // mach was bei Taste MENU_OK
33
}
34
35
// etc.

>Cool, so habe ich auch gedacht, die Taster-If's in die Switch-Ebenen
>einzubauen und darauf hoffen, dass sie dann entsprechen innerhalb der
>Switch-Ebenen funktionieren, d.h. dass der Menü-Button automatisch zum
>Ok-Button wird. Denke ich so richtig?

Ja.

von Ardu (Gast)


Lesenswert?

Ahaaa, super, das sind mal super Wegweiser, so ergibt sich auch mehr ein 
Sinn aus den Beispielen, die ich so ergoogelt habe, und zwar eure beiden 
Antworten. Das mit den Funktionen, also "void menu", "void submenu" 
etc., die dann über die Tasten-Switches abgerufen werden, und in diesem 
Zusammenhang auch das Tasterbeispiel, welches sich ebenso in den 
Beispielen findet, aber komplizierter und mit timer, aber da das jetzt 
mehr Sinn für mich ergibt, werden ich die noch einige Male lesen, bis 
ich wieder "ahaa" denke ;P

Hab mit folgendem Code angefangen zu lernen, bin noch Anfänger, verstehe 
aber schon recht viel, bin erstaunt darüber, wie verhätnismäßig einfach 
Arduino ist, liegt zwar auch daran, dass ich Visual Basic, HTML und Java 
gelernt habe, da bin ich  etwa fortschrittlicher Anfänger, aber 
dennoch...

Jedenfalls ist da eine "flash"-Funktion eingebaut, die den Timer 
darstellt, verstehe diese aber erstens nicht ganz und zweitens gefällt 
mir auch nicht, dass das Blinke des Rechtecks, (display.drawRect), 
ungleichmäßig ist, etwa vier Mal und dann kurzer Hänger, so reagieren 
auch die I/O, also Taster und LED, diese Blinken exakt im selben Takt, 
ist zwar nur einen Software-Bastelei zum Üben, aber wenn ich weiter gehe 
und über Transistoren schalten will, ist das wohl sehr unvorteilhaft. 
Andereseits sorgt das "flash"en für eine saubere Aktualisierung des 
Displays, die Sekunden fangen an bei einer Verzögerung von 250ms zu 
stocken. Weiss also nicht so konkret wie ich da vorgehen soll.

Ich merke aufgrund der langen Antwortzeiten und weiss, dass das Thema 
nicht so reizvoll ist und vielleicht sogar nervt, aber als Anfänger 
braucht man eben diese Denkanstöße, daher bin ich euch sehr dankbar 
dafür und für weitere Hilfe.

Wünsche euch noch ein schönes Wochenende und vielen lieben Dank nochmals 
:)

Code:
1
#include <SPI.h> //Library for Adafruit communication to OLED display
2
#include <Wire.h> //I2C communication library
3
#include "ds3231.h" //Real Time Clock library
4
#include <Adafruit_GFX.h> //Graphics library
5
#include <Adafruit_SSD1306.h> //OLED display library
6
7
uint8_t secset = 0; //Index for second RTC setting
8
uint8_t minset = 1; //Index for minute RTC setting
9
uint8_t hourset = 2; //Index for hour RTC setting
10
uint8_t wdayset = 3; //Index for weekday RTC setting
11
uint8_t mdayset = 4; //Index for date RTC setting
12
uint8_t monset = 5; //Index for month RTC setting
13
uint8_t yearset = 6; //Index for year RTC setting
14
15
//Alarm time variables
16
uint8_t wake_HOUR = 0;
17
uint8_t wake_MINUTE = 0;
18
uint8_t wake_SECOND = 0;
19
uint8_t wake_SET = 1; //Default alarm to ON in case of power failure or reset
20
21
#define OLED_RESET 4 //Define reset for OLED display
22
Adafruit_SSD1306 display(OLED_RESET); //Reset OLED display
23
24
//Check for proper display size - required
25
#if (SSD1306_LCDHEIGHT != 64)
26
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
27
#endif
28
29
unsigned long prev, interval = 100; //Variables for display/clock update rate
30
byte flash = 0; //Flag for display flashing - toggle once per update interval
31
byte mode = 0; //Mode for time and date setting
32
int tempset; //Temporary variable for setting time/date
33
int beepcount = 0; //Variable for number of 100ms intervals since alarm started sounding
34
35
36
void setup()
37
{
38
Serial.begin(9600); //Initialize serial port, if needed (not used)
39
Wire.begin(); //Initialize I2C communication library
40
DS3231_init(0x00); //Initialize Real Time Clock for 1Hz square wave output (no RTC alarms on output pin)
41
42
pinMode(8, INPUT); //Set pin for time/date mode button to input
43
digitalWrite(8, HIGH); //Turn on pullup resistors
44
45
pinMode(9, INPUT); //Set pin for time/date set button to input
46
digitalWrite(9, HIGH); //Turn on pullup resistors
47
48
pinMode(10, OUTPUT); //Set pin for external alarm indicator output
49
digitalWrite(10, LOW); //Initialize external alarm to off state
50
    
51
    
52
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
53
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64 OLED display)
54
display.setTextSize(1); //Set default font size to the smalles
55
display.setTextColor(WHITE); //Set font to display color on black background
56
// init done
57
}
58
59
void loop()
60
{
61
char tempF[6]; //Local variable to store converted temperature reading from Real Time Clock module
62
float temperature; //Intermediate temperature variable to convert Celsius to Farenheit
63
unsigned long now = millis(); //Local variable set to current value of Arduino internal millisecond run-time timer
64
struct ts t; //Structure for retrieving and storing time and date data from real time clock
65
66
//Draw and update display every refresh period (100ms)
67
if ((now - prev > interval)) { //Determine whether to start a time and screen update
68
  if(flash == 0){flash = 1;}else{flash = 0;} //Toggle flash flag for cursor blinking later
69
  DS3231_get(&t); //Get time and date and save in t structure
70
  
71
  get_alarm(); //Retrieve current alarm setting
72
  digitalWrite(10, LOW); //Turn off external alarm for flashing
73
  
74
  //Force a temperature conversion if one is not in progress for rapid update and better clock accuracy
75
  //Maintain 1Hz square wave output
76
  if((DS3231_get_addr(0x0E) & 0x20) == 0){DS3231_init(0x20);} //Check for CONV flag to see if conversion is in progress first, else start conversion
77
  temperature = DS3231_get_treg(); //Get temperature from real time clock
78
  temperature = (temperature * 1.8) + 32.0; // Convert Celsius to Fahrenheit
79
  dtostrf(temperature, 5, 1, tempF); //Convert temperature to string for display
80
81
  display.clearDisplay(); //Clear display buffer from last refresh
82
  
83
//NOTE: Alarm indicators are overwritten in display buffer if full-screen animation is displayed, so no check for that  
84
  if (mode <= 7){ //Alarm indicators and actions in normal and time set display mode only
85
  if (wake_SET){ //Display alarm on indicator if alarm turned on
86
    display.setCursor(43, 55); //Position text cursor for alarm on indicator
87
    display.print("*"); //Print character inside lower left corner of analog clock if alarm on
88
  }
89
  }
90
91
  if(wake_SET && DS3231_triggered_a1()){ //Display/sound alarm if enabled and triggered
92
      beepcount = beepcount + 1;
93
      if(beepcount <= 600){ //Sound alarm for 60 seconds
94
        if(!flash){ //Flash display and sound interrupted beeper
95
        if(mode <= 7){display.setCursor(81, 55); display.print("*");} //Flash alarm triggered indicator in lower right corner of analog clock, if displayed
96
        digitalWrite(10, HIGH); //Flash external alarm if alarm triggered, regardless of mode
97
        }
98
      }
99
      else{beepcount = 0; DS3231_clear_a1f();} //If alarm has sounded for 1 minute, reset alarm timer counter and alarm flag
100
  }
101
102
  if (mode <=7){      
103
  display.setCursor(92,8); //Set cursor for temperature display
104
  display.print(tempF); //Send temperature to display buffer
105
  display.drawCircle(124,8,2,WHITE); //Draw degree symbol after temperature
106
107
//DO NOT CHANGE CURSOR POSITIONING OF TIME AND DATE TEXT FIELDS OR TIME/DATE SET CURSOR WON'T MATCH!!!     
108
  display.setCursor(0,0); //Position cursor for day-of-week display
109
  printDay(t.wday); //Lookup day of week string from retrieved RTC data and write to display buffer
110
        
111
  printMonth(t.mon); //Lookup month string from retrieved RTC data and write to display buffer
112
        
113
  if(t.mday<10){display.print("0");} //Add leading zero to date display if date is single-digit
114
  display.print(t.mday); //Write date to display buffer
115
  display.print(", "); //Write spaces and comma between date and year
116
        
117
  display.print(t.year); //Write year to display buffer
118
        
119
  display.setCursor(0, 8); //Position text cursor for time display
120
        
121
  //RTC is operated in 24-hour mode and conversion to 12-hour mode done here, in software
122
  if(t.hour == 0){display.print("12");} //Convert zero hour for 12-hour display
123
    else if(t.hour < 13 && t.hour >= 10){display.print(t.hour);} //Just display hour if double digit hour
124
        else if(t.hour < 10){display.print(" "); display.print(t.hour);} //If single digit hour, add leading space
125
        else if(t.hour >= 13 && t.hour >= 22){display.print(t.hour-12);} //If double digit and PM, convert 24 to 12 hour
126
        else{display.print(" "); display.print(t.hour-12);} //If single digit and PM, convert to 12 hour and add leading space
127
        
128
        display.print(":"); //Display hour-minute separator
129
        if(t.min<10){display.print("0");} //Add leading zero if single-digit minute
130
        display.print(t.min); //Display retrieved minutes
131
        
132
        display.print(":"); //Display minute-seconds separator
133
        if(t.sec<10){display.print("0");} //Add leading zero for single-digit seconds
134
        display.print(t.sec); //Display retrieved seconds
135
        
136
        if(t.hour < 12){display.print(" AM");} //Display AM indicator, as needed
137
        else{display.print(" PM");} //Display PM indicator, as needed
138
              
139
140
    // Now draw the clock face
141
    display.drawCircle(display.width()/2, display.height()/2 + 8, 20, WHITE); //Draw and position clock outer circle
142
    //display.fillCircle(display.width()/2+25, display.height()/2 + 8, 20, WHITE); //Fill circle only if displaying inverted colors
143
    if(flash){display.drawCircle(display.width()/2, display.height()/2 + 8, 2, WHITE);} //Draw, position and blink tiny inner circle
144
    display.drawRect(41,17,47,47,WHITE); //Draw box around clock
145
146
    //Position and draw hour tick marks
147
    for( int z=0; z < 360;z= z + 30 ){
148
    //Begin at 0° and stop at 360°
149
      float angle = z ;
150
      angle=(angle/57.29577951) ; //Convert degrees to radians
151
      int x2=(64+(sin(angle)*20));
152
      int y2=(40-(cos(angle)*20));
153
      int x3=(64+(sin(angle)*(20-5)));
154
      int y3=(40-(cos(angle)*(20-5)));
155
      display.drawLine(x2,y2,x3,y3,WHITE);
156
    }
157
  
158
    //Position and display second hand
159
    float angle = t.sec * 6 ; //Retrieve stored seconds and apply
160
    angle=(angle/57.29577951) ; //Convert degrees to radians  
161
    int x3=(64+(sin(angle)*(20)));
162
    int y3=(40-(cos(angle)*(20)));
163
    display.drawLine(64,40,x3,y3,WHITE);
164
165
   //Position and display minute hand
166
    angle = t.min * 6; //Retrieve stored minutes and apply
167
    angle=(angle/57.29577951) ; //Convert degrees to radians  
168
    x3=(64+(sin(angle)*(20-3)));
169
    y3=(40-(cos(angle)*(20-3)));
170
    display.drawLine(64,40,x3,y3,WHITE);
171
172
    //Position and display hour hand
173
    angle = t.hour * 30 + int((t.min / 12) * 6); //Retrieve stored hour and minutes and apply
174
    angle=(angle/57.29577951) ; //Convert degrees to radians  
175
    x3=(64+(sin(angle)*(20-11)));
176
    y3=(40-(cos(angle)*(20-11)));
177
    display.drawLine(64,40,x3,y3,WHITE);
178
  }
179
  
180
    if (mode > 7){ 
181
      display.setCursor(0, 0); //Position text cursor
182
      display.print("Alarm Set: ");
183
      if(wake_SET){display.print("ON");}else{display.print("OFF");}
184
      display.setCursor(0, 8); //Position text cursor for time display
185
        
186
      //RTC is operated in 24-hour mode and conversion to 12-hour mode done here, in software
187
      if(wake_HOUR == 0){display.print("12");} //Convert zero hour for 12-hour display
188
        else if(wake_HOUR < 13 && wake_HOUR >= 10){display.print(wake_HOUR);} //Just display hour if double digit hour
189
            else if(wake_HOUR < 10){display.print(" "); display.print(wake_HOUR);} //If single digit hour, add leading space
190
            else if(wake_HOUR >= 13 && wake_HOUR >= 22){display.print(wake_HOUR-12);} //If double digit and PM, convert 24 to 12 hour
191
            else{display.print(" "); display.print(wake_HOUR-12);} //If single digit and PM, convert to 12 hour and add leading space
192
        
193
            display.print(":"); //Display hour-minute separator
194
            if(wake_MINUTE<10){display.print("0");} //Add leading zero if single-digit minute
195
            display.print(wake_MINUTE); //Display retrieved minutes
196
        
197
            display.print(":"); //Display minute-seconds separator
198
            if(wake_SECOND<10){display.print("0");} //Add leading zero for single-digit seconds
199
            display.print(wake_SECOND); //Display retrieved seconds
200
        
201
            if(wake_HOUR < 12){display.print(" AM");} //Display AM indicator, as needed
202
            else{display.print(" PM");} //Display PM indicator, as needed
203
    }
204
205
 
206
//Time/Date setting button processing and cursor flashing
207
//CURSOR COORDINATES ARE SET TO MATCH TIME/DATE FIELD - DO NOT CHANGE!!
208
//Digital and analog time/date display updates with new settings at 5Hz as settings are changed
209
  switch(mode)
210
  {
211
    case 0: break;
212
    case 1: //Day-of-week setting
213
      if(flash){display.drawRect(0,0,18,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
214
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
215
        tempset = t.wday; //Get the current weekday and save in temporary variable
216
        tempset = tempset + 1; //Increment the day at 5Hz rate
217
        if(tempset > 7){tempset = 1;} //Roll over after 7 days
218
        t.wday = tempset; //After each update, write the day back to the time structure
219
        set_rtc_field(t, wdayset); //Write the set field only back to the real time clock module after each update
220
      }
221
      break;
222
    case 2: //Month setting
223
      if(flash){display.drawRect(24,0,18,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
224
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
225
        tempset = t.mon; //Get the current month and save in temporary variable
226
        tempset = tempset + 1; //Increment the month at 5Hz rate
227
        if(tempset > 12){tempset = 1;} //Roll over after 12 months
228
        t.mon = tempset; //After each update, write the month back to the time structure
229
        set_rtc_field(t, monset); //Write the set field only back to the real time clock module after each update
230
      }
231
      break;
232
    case 3: //Date setting
233
      if(flash){display.drawRect(48,0,12,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
234
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
235
        tempset = t.mday; //Get the current date and save in temporary variable
236
        tempset = tempset + 1; //Increment the date at 5Hz rate
237
        //(RTC allows incorrect date setting for months < 31 days, but will use correct date rollover for subsequent months.
238
        if(tempset > 31){tempset = 1;} //Roll over after 31 days
239
        t.mday = tempset; //After each update, write the date back to the time structure 
240
        set_rtc_field(t, mdayset); //Write the set field only back to the real time clock module after each update
241
      }
242
      break;
243
    case 4: //Year setting
244
      if(flash){display.drawRect(72,0,24,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
245
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
246
        tempset = t.year; //Get the current year and save in temporary variable
247
        tempset = tempset + 1; //Increment the year at 5Hz rate
248
        //RTC allows setting from 1900, but range limited here to 2000 to 2099
249
        if(tempset > 2099){tempset = 2000;} //Roll over after 2099 to 2000
250
        t.year = tempset; //After each update, write the year back to the time structure
251
        set_rtc_field(t, yearset); //Write the set field only back to the real time clock module after each update
252
      } 
253
      break;
254
    case 5: //Hour setting
255
      if(flash){display.drawRect(0,8,12,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
256
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
257
        tempset = t.hour; //Get the current hour and save in temporary variable
258
        tempset = tempset + 1; //Increment the hour at 5Hz rate
259
        if(tempset > 23){tempset = 0;} //Roll over hour after 23rd hour (setting done in 24-hour mode)
260
        t.hour = tempset; //After each update, write the hour back to the time structure
261
        set_rtc_field(t, hourset); //Write the set field only back to the real time clock module after each update
262
      }
263
      break;
264
    case 6: //Minute setting
265
      if(flash){display.drawRect(18,8,12,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
266
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
267
        tempset = t.min; //Get the current minute and save in temporary variable
268
        tempset = tempset + 1; //Increment the minute at 5Hz rate
269
        if(tempset > 59){tempset = 0;} //Roll over minute to zero after 59th minute
270
        t.min = tempset; //After each update, write the minute back to the time structure
271
        set_rtc_field(t, minset); //Write the set field only back to the real time clock module after each update
272
      }
273
      break;
274
      
275
     //Set clock + 1 minute, then press and hold to freeze second setting.
276
     //Release button at 00 seconds to synchronize clock to external time source.
277
    case 7: //Second synchronization
278
      if(flash){display.drawRect(36,8,12,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
279
      if(!digitalRead(9) && (!flash)){ //Reset second to zero at 5Hz rate if button held down
280
        t.sec = 0; //After each update, write the zeroed second back to the time structure
281
        set_rtc_field(t, secset); //Write the set field only back to the real time clock module after each update
282
      }
283
      break;
284
      
285
      
286
    case 8: //Alarm hour setting
287
      if(flash){display.drawRect(0,8,12,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
288
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
289
        tempset = wake_HOUR; //Get the current hour and save in temporary variable
290
        tempset = tempset + 1; //Increment the hour at 5Hz rate
291
        if(tempset > 23){tempset = 0;} //Roll over hour after 23rd hour (setting done in 24-hour mode)
292
        wake_HOUR = tempset; //After each update, write the hour back to the alarm variable
293
        set_alarm(); //Write the alarm setting back to the RTC after each update
294
      }
295
    break;
296
    
297
    
298
    case 9: //Alarm minute setting
299
      if(flash){display.drawRect(18,8,12,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
300
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
301
        tempset = wake_MINUTE; //Get the current minute and save in temporary variable
302
        tempset = tempset + 1; //Increment the minute at 5Hz rate
303
        if(tempset > 59){tempset = 0;} //Roll over minute to zero after 59th minute
304
        wake_MINUTE = tempset; //After each update, write the minute back to the alarm variable
305
        set_alarm(); //Write the alarm setting back to the RTC after each update
306
      }
307
    break;
308
    
309
     case 10: //Alarm enable/disable
310
      if(flash){display.drawRect(66,0,18,8,WHITE);} //Display rectangle cursor every other display update (5Hz blink)
311
      if(!digitalRead(9) && (!flash)){ //Update setting at 5Hz rate if button held down
312
        if(wake_SET){wake_SET = 0;}else{wake_SET = 1;} //Toggle alarm on/of variable at 5 Hz
313
      }
314
    break;
315
  }
316
        
317
prev = now; //Reset variable for display and time update rate
318
display.display(); //Display the constructed frame buffer for this framecount
319
    }
320
    
321
//Clock setting mode set - outside time/display update processing for faster button response
322
if(!digitalRead(8)){ //Read setting mode button
323
  delay(25); //25ms debounce time
324
  if(!digitalRead(8)){ //Activate setting mode change after 100ms button press
325
    mode = mode + 1; //Increment the time setting mode on each button press
326
    if(mode > 10){mode = 0;} //Roll the mode setting after 7th mode
327
    while(!digitalRead(8)){} //Wait for button release (freezes all display processing and time updates while button held, but RTC continues to keep time)
328
  }
329
 }
330
 
331
 if(!digitalRead(9)){ //Reset alarm flag if set button pressed
332
   delay(25); //25ms debounce time
333
   if(!digitalRead(9)){DS3231_clear_a1f();} //Clear alarm flag if set button pressed - insures alarm reset when turning alarm on
334
 }
335
}
336
337
338
339
//Function to display month string from numerical month argument
340
void printMonth(int month)
341
{
342
  switch(month)
343
  {
344
    case 1: display.print("Jan ");break;
345
    case 2: display.print("Feb ");break;
346
    case 3: display.print("Mar ");break;
347
    case 4: display.print("Apr ");break;
348
    case 5: display.print("May ");break;
349
    case 6: display.print("Jun ");break;
350
    case 7: display.print("Jul ");break;
351
    case 8: display.print("Aug ");break;
352
    case 9: display.print("Sep ");break;
353
    case 10: display.print("Oct ");break;
354
    case 11: display.print("Nov ");break;
355
    case 12: display.print("Dec ");break;
356
    default: display.print("--- ");break; //Display dashes if error - avoids scrambling display
357
  } 
358
}
359
360
361
//Function to display day-of-week string from numerical day-of-week argument
362
void printDay(int day)
363
{
364
  switch(day)
365
  {
366
    case 1: display.print("Mon ");break;
367
    case 2: display.print("Tue ");break;
368
    case 3: display.print("Wed ");break;
369
    case 4: display.print("Thu ");break;
370
    case 5: display.print("Fri ");break;
371
    case 6: display.print("Sat ");break;
372
    case 7: display.print("Sun ");break;
373
    default: display.print("--- ");break; //Display dashes if error - avoids scrambling display
374
  } 
375
}
376
377
//Subroutine to adjust a single date/time field in the RTC
378
void set_rtc_field(struct ts t,  uint8_t index)
379
{
380
    uint8_t century;
381
382
    if (t.year > 2000) {
383
        century = 0x80;
384
        t.year_s = t.year - 2000;
385
    } else {
386
        century = 0;
387
        t.year_s = t.year - 1900;
388
    }
389
390
    uint8_t TimeDate[7] = { t.sec, t.min, t.hour, t.wday, t.mday, t.mon, t.year_s };
391
392
    Wire.beginTransmission(DS3231_I2C_ADDR);
393
    Wire.write(index);
394
        TimeDate[index] = dectobcd(TimeDate[index]);
395
        if (index == 5){TimeDate[5] += century;}
396
        Wire.write(TimeDate[index]);
397
    Wire.endTransmission();
398
    
399
    //Adjust the month setting, per data sheet, if the year is changed
400
    if (index == 6){
401
      Wire.beginTransmission(DS3231_I2C_ADDR);
402
      Wire.write(5);
403
      TimeDate[5] = dectobcd(TimeDate[5]);
404
      TimeDate[5] += century;
405
      Wire.write(TimeDate[5]);
406
      Wire.endTransmission();
407
    } 
408
}
409
410
411
//Subroutine to set alarm 1
412
void set_alarm()
413
{
414
415
    // flags define what calendar component to be checked against the current time in order
416
    // to trigger the alarm - see datasheet
417
    // A1M1 (seconds) (0 to enable, 1 to disable)
418
    // A1M2 (minutes) (0 to enable, 1 to disable)
419
    // A1M3 (hour)    (0 to enable, 1 to disable) 
420
    // A1M4 (day)     (0 to enable, 1 to disable)
421
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
422
    boolean flags[5] = { 0, 0, 0, 1, 1 }; //Set alarm to trigger every 24 hours on time match
423
424
    // set Alarm1
425
    DS3231_set_a1(0, wake_MINUTE, wake_HOUR, 0, flags); //Set alarm 1 RTC registers
426
427
}
428
429
//Subroutine to get alarm 1
430
void get_alarm()
431
{
432
    uint8_t n[4];
433
    uint8_t t[4];               //second,minute,hour,day
434
    uint8_t f[5];               // flags
435
    uint8_t i;
436
437
    Wire.beginTransmission(DS3231_I2C_ADDR);
438
    Wire.write(DS3231_ALARM1_ADDR);
439
    Wire.endTransmission();
440
441
    Wire.requestFrom(DS3231_I2C_ADDR, 4);
442
443
    for (i = 0; i <= 3; i++) {
444
        n[i] = Wire.read();
445
        f[i] = (n[i] & 0x80) >> 7;
446
        t[i] = bcdtodec(n[i] & 0x7F);
447
    }
448
449
    f[4] = (n[3] & 0x40) >> 6;
450
    t[3] = bcdtodec(n[3] & 0x3F);
451
    
452
    wake_SECOND = t[0];
453
    wake_MINUTE = t[1];
454
    wake_HOUR = t[2];
455
}

von Falk B. (falk)


Lesenswert?

@ Ardu (Gast)

>Jedenfalls ist da eine "flash"-Funktion eingebaut, die den Timer
>darstellt, verstehe diese aber erstens nicht ganz

Das ist eine ganz normale Variable, welche als bool-Wert genutzt wird. 
Bei jedem Aufruf deines Riesenkonstrukts

>if ((now - prev > interval)) { //Determine whether to start a time and screen 
update

wird flash invertiert.

>  if(flash == 0){flash = 1;}else{flash = 0;} //Toggle flash flag for cursor 
blinking later

Das kann man auch deutlich einfacher schreiben.

flash = !flash;

Damit wechselt (eng. toggle) der Wert bei jedem Durchlauf des 
Konstrukts, damit kann man ein Blinken eines Cursors steuern. Und genau 
das wird auch gemacht.


>und zweitens gefällt
>mir auch nicht, dass das Blinke des Rechtecks, (display.drawRect),
>ungleichmäßig ist, etwa vier Mal und dann kurzer Hänger, so reagieren
>auch die I/O, also Taster und LED, diese Blinken exakt im selben Takt,

Tja, das ist das Problem der blockierenden Programmierweise. Sagte ich 
bereits. Es gibt KEINEN Grund, auf das Loslassen der Taste zu warten. 
Man muss den Zustandswechsel der Taste erkennen und auswerten. Siehe 
mein Beispiel!
Weiterhin sind an einigen Stellen ein paar eher aufwändige Rechnungen 
drin, die dauern eine Weile, das könnte der Grund für das ungleichmäßige 
Anzeigen sein, denn diese Anzeigen sind von der Variablen flash 
abhängig.
Das hier z.B.
1
    //Position and draw hour tick marks
2
    for( int z=0; z < 360;z= z + 30 ){
3
    //Begin at 0° and stop at 360°
4
      float angle = z ;
5
      angle=(angle/57.29577951) ; //Convert degrees to radians
6
      int x2=(64+(sin(angle)*20));
7
      int y2=(40-(cos(angle)*20));
8
      int x3=(64+(sin(angle)*(20-5)));
9
      int y3=(40-(cos(angle)*(20-5)));
10
      display.drawLine(x2,y2,x3,y3,WHITE);
11
    }

>ist zwar nur einen Software-Bastelei zum Üben, aber wenn ich weiter gehe
>und über Transistoren schalten will, ist das wohl sehr unvorteilhaft.
>Andereseits sorgt das "flash"en für eine saubere Aktualisierung des
>Displays, die Sekunden fangen an bei einer Verzögerung von 250ms zu
>stocken.

Wie meinst du das? Welche Verzögerung und wo?

Noch ein Tipp. Die Formatierung deines Quelltextes ist 
verbesserungsfähig. Sowas macht man nicht!
1
if(t.hour == 0){display.print("12");} //Convert zero hour for 12-hour display
2
    else if(t.hour < 13 && t.hour >= 10){display.print(t.hour);} //Just display hour if double digit hour
3
        else if(t.hour < 10){display.print(" "); display.print(t.hour);} //If single digit hour, add leading space
4
        else if(t.hour >= 13 && t.hour >= 22){display.print(t.hour-12);} //If double digit and PM, convert 24 to 12 hour
5
        else{display.print(" "); display.print(t.hour-12);} //If single digit and PM, convert to 12 hour and add leading space
6
        
7
        display.print(":"); //Display hour-minute separator
8
        if(t.min<10){display.print("0");} //Add leading zero if single-digit minute
9
        display.print(t.min); //Display retrieved minutes
10
        
11
        display.print(":"); //Display minute-seconds separator
12
        if(t.sec<10){display.print("0");} //Add leading zero for single-digit seconds
13
        display.print(t.sec); //Display retrieved seconds
14
        
15
        if(t.hour < 12){display.print(" AM");} //Display AM indicator, as needed
16
        else{display.print(" PM");} //Display PM indicator, as needed

Das ist maximal irreführend und man sieht nicht, in welchen Block was 
reingehört!

Strukturierte Programmierung auf Mikrocontrollern

Besser so.
1
if(t.hour == 0) {//Convert zero hour for 12-hour display
2
  display.print("12");
3
} else if(t.hour < 13 && t.hour >= 10) { //Just display hour if double digit hour
4
  display.print(t.hour);
5
} else if(t.hour < 10) { //If single digit hour, add leading space
6
  display.print(" "); display.print(t.hour);
7
} else if(t.hour >= 13 && t.hour >= 22) { //If double digit and PM, convert 24 to 12 hour
8
  display.print(t.hour-12);
9
} else { //If single digit and PM, convert to 12 hour and add leading space
10
  display.print(" "); display.print(t.hour-12);
11
}       
12
display.print(":"); //Display hour-minute separator
13
if(t.min<10) { //Add leading zero if single-digit minute
14
  display.print("0");
15
} 
16
display.print(t.min); //Display retrieved minutes
17
18
display.print(":"); //Display minute-seconds separator
19
if (t.sec<10) { //Add leading zero for single-digit seconds
20
  display.print("0");
21
}
22
display.print(t.sec); //Display retrieved seconds
23
24
if(t.hour < 12) {  //Display AM indicator, as needed
25
  display.print(" AM");
26
} else {           //Display PM indicator, as needed
27
 
28
  display.print(" PM");
29
}

Last but not least solltest auch du dich mit dem Thema Netiquette 
beschäftigen. Lange Quelltexte gehören in den Anhang!

von Ardu (Gast)


Lesenswert?

Ok, ja, ich hatte überlegt, ob ich die .ino dranhängen soll oder den 
Code komplett so, das ist auch der Ursprungscode, den habe ich stark 
abgeändert, ging ja erstmal hauptsächlich um die flash funktion und 
damit das klarer ist und meine Veränderungen nicht verwirren, habe ich 
den originalen gepostet. die RTC_Clock.ino habe ich auf dem Handy meinen 
Code auf dem PC, kann ich ja posten, wenn ich später am PC bin.

Ich entschuldige mich erstmal für die fehlende Nettiquette und für meine 
langen und teils schwer verständlichen Texte, aber das ist ein Problem, 
das ich so nicht lösen kann.

Die von dir angemerkten Fehler habe ich nicht mehr in meinem Code, die 
meisten Spielereien sind draussen. Das Konstrukt ist jetzt nicht mehr 
ganz so riesig, aber für meinen Geschmack immer noch zu groß. Ich nutze 
ein anderes Display, das PCD8544, und will auch nicht, dass der Cursor 
blinkt, das soll eigentlich garnichts blinken, will aber eine Markierung 
des ausgewählten Menüpunktes, so wie es bei z.B. einem Nokia 3310 ist, 
denke auch einfach die Farbe des gewählten zu invertieren, anstatt des 
Rechtecks, aber das ist im Moment total irrelevant, eine spitze Klammer 
reicht auch zum Basteln.

Ich meine diese Verzögerung:
1
unsigned long prev, interval = 100; //Variables for display/clock update rate
2
byte flash = 0; //Flag for display flashing - toggle once per update interval

Habe in meinem Code auch eine Strukturierung rein gebracht und viele 
Anmerkungen und Überschriften geändert und ergänzt, habs nur englisch 
gehalten. Auch lasse ich den Code regelmäßig von der Arduino IDE 
automatisch formatieren. Grad als Anfänger finden ich das ist die 
absolute Basis, dass man es auch richtig lernen kann, deswegen brauche 
ich ja immer wieder eure Hilfe, weil viele der Beispiele nach dem Motto 
"hauptsache Speichesparend und funktional" geschrieben sind und aus der 
Sicht von Leuten, die es einfach drauf haben, ich weiss aus anderen 
Bereichen, dass dann einem die Sicht des Anfängers verloren gehen kann, 
die Anmerkungen sind meist nicht gleich schlüssig, deswgen ist es gut, 
dass du konkrete Beispiele postest und sie kurz erläuterst, ich kenne 
sie aus Beispielen und kann sie eben durch unschlüssige Anmerkungen 
nicht verstehen, so aber klickts ;)

von Falk B. (falk)


Lesenswert?

@ Ardu (Gast)

>Ich meine diese Verzögerung:

>unsigned long prev, interval = 100; //Variables for display/clock update >rate

Wie ich bereits sagte. Die Funktion loop() wird beim Arduino in einer 
Endlosschleife aufgerufen. Im "echten" C würde das so aussehen.

main () {

setup();

while(1) loop();

}

In deiner loop() Funktion wird geprüft, ob die Differenz zwischen now 
und prev > intervall ist. Wenn ja, wird dein Konstrukt ausgeführt, 
sprich, ein Menuupdate. now ist eine Variable aus dem Arduino-Framework, 
sie wird mittles Timer-Interrupt im 1ms Takt hochgezählt. Siehe 
Arduino-Doku.

https://www.arduino.cc/en/Reference/Millis
1
if ((now - prev > interval)) { //Determine whether to start a time and screen update

von Ardu (Gast)


Lesenswert?

Das habe ich ja verstanden, aber du hattest gefragt welche Verzögerung 
und wo, wenn ich da den Wert höher setze, stocken wie erwähnt die 
Sekunden, aber eigentlich müssten die Sekunden auch so im Loop immer im 
richtigen Takt angezeigt werden, oder?
Bin auch nicht sicher, ob diese kurze Verzögerung nach allen ca. 4 
"flash"es irgendwas mit dem Kodensator am PCD8544 zutun hat, dass es auf 
das Loslassen des Tasters wartet klingt für mich schon logischer. 
Ansonsten will ich ja das flashen komplett weg haben und nur einen Timer 
zum Entprellen der Taster, es ist nur wegen den Sekunden und dem Display 
noch drin, weil dieses damit auch etwas besser läuft, in meinen ersten 
Versuchen mit der PCD8544 Library von carlosefr blinkt das Display auch 
bei jedem Loop-Beginn, das Flackern ist also so ein grundsätzliches 
Problem, könnte auch, wie du es erwähnt hast, am display.clearDisplay() 
liegen, muss ich auch mal ausprobieren.
Das Menü-Update müsste doch eigentlich ebenso wie die Sekunden im Loop 
aktualisiert werden, oder?
Was ein Loop ansich ist, ist mir schon klar, aber noch nicht genau der 
Zusammenhang und der Einfluss den ich nehmen muss, damit das alles 
ordentlich angezeigt wird und auch die I/O's nicht flackern.

Setzt mich später wenn ich Zeit hab vor den Rechner, ergänze und 
verändere meinen Code dann soweit und hänge ihn hier mit dran, hoffe 
du bist dann noch/wieder da :)

Last but not least, thanks again a lot :)

von Falk B. (falk)


Lesenswert?

@ Ardu (Gast)

>Das habe ich ja verstanden, aber du hattest gefragt welche Verzögerung
>und wo, wenn ich da den Wert höher setze, stocken wie erwähnt die
>Sekunden,

Das sollte man aber auch so sagen, ich kann nicht hellsehen (weil ich ja 
in Dunkeldeutschland wohne . . .)
Siehe Netiquette.

> aber eigentlich müssten die Sekunden auch so im Loop immer im
>richtigen Takt angezeigt werden, oder?

Ja. Aber nur dann, wenn der Durchlauf deiner Anzeige nicht länger als 
ein Timerzyklus ist, hier dein interval.

>Bin auch nicht sicher, ob diese kurze Verzögerung nach allen ca. 4
>"flash"es irgendwas mit dem Kodensator am PCD8544 zutun hat,

HALLLOOOOO!!!! Ist dir auch schon mal EINE Sekunde in den Sinn gekommen, 
daß ich NICHT neben dir sitze und nicht mal ANSATZWEISE sehe was du 
siehst, geschweige denn was in deinem Kopf vorgeht?

https://www.mikrocontroller.net/articles/Netiquette#Klare_Beschreibung_des_Problems

Wenn du ein Problem des Schaltplans diskutieren willst, mußt du den 
mitliefern!

> dass es auf
>das Loslassen des Tasters wartet klingt für mich schon logischer.

Na dan mach den Unsinn doch endlich mal raus! Wie man es gescheit macht, 
hab ich dir doch schon gezeigt!!!

>Ansonsten will ich ja das flashen komplett weg haben

Auch hier solltest du dich um eine klarere Sprache bemühen. "Flashen" 
ist im Umfeld von Mikrocontrollern der Vorgang zum Programmieren der 
Firmware. Du redest von der Variable flash in deinem Programm zum 
Blinken.

Ausserdem, wo ist das Problem? Mach die Variable weg und alle Abfragen 
darauf auch. Flashen weg.

> und nur einen Timer
>zum Entprellen der Taster,

> es ist nur wegen den Sekunden und dem Display
>noch drin, weil dieses damit auch etwas besser läuft, in meinen ersten
>Versuchen mit der PCD8544 Library von carlosefr blinkt das Display auch
>bei jedem Loop-Beginn, das Flackern ist also so ein grundsätzliches
>Problem, könnte auch, wie du es erwähnt hast, am display.clearDisplay()
>liegen, muss ich auch mal ausprobieren.

Dann tu das doch einfach!

>Das Menü-Update müsste doch eigentlich ebenso wie die Sekunden im Loop
>aktualisiert werden, oder?

Ja.

von Ardu (Gast)


Angehängte Dateien:

Lesenswert?

Wie geschrieben fällt es mir schwer mich schriftlich auszudrücken, 
entschuldigung nochmals dafür.
Ich habe ja soweit alles verstanden und weiss wie ich das "flash"en 
entferne, nur war mir bislang nicht klar wie wichtig das ist wegen der 
Zeitanzeige und der Menü-Aktualisierungund, das geht doch aber aus 
meinem Text klar hervor, du kannst ja einfach fragen, wenn Informationen 
fehlen.
Das Display ist standartmäßig angeschlossen, wie in angehängter Grafik.

Ich will dir hier nicht dein Wochenende schlecht machen, sondern auch 
ein Feedback geben, um dir eben auch zu schildern was und wie ich denke 
und was ich vorhabe, bei den Fragen ist ein Fragezeichen am Ende und bei 
den Aussagen nicht, diese kannst du natürlich gerne kommentieren, eben 
in dem Fall, dass ich falsch denke, aber es sind keine wiederholten 
Fragen, die beantwortest du perfekt, wie schon erwäht. Da verstehe ich 
dein Problem nicht, denke da liegt ein Missverständnis vor. Kritik ist 
immer gerne willkommen, aber bitte gerechtfertigt.

von Falk B. (falk)


Lesenswert?

@ Ardu (Gast)

>Das Display ist standartmäßig angeschlossen, wie in angehängter Grafik.

Ist OK, der Kondensator hat mit dem Flackern nichts zu tun. Es ist ein 
Entkoppelkondensator für das LCD.

https://www.mikrocontroller.net/articles/Kondensator#Entkoppelkondensator

>dein Problem nicht, denke da liegt ein Missverständnis vor.

Scheint wohl so.

Also dann, viel Spaß noch beim Programmieren.

von Joachim B. (jar)


Lesenswert?

Ardu schrieb:
> Kritik ist
> immer gerne willkommen, aber bitte gerechtfertigt.

OK

Ardu schrieb:
> standartmäßig

weil der Spruch so toll ist zitier ich mal:

In Africa gibt es einen Stamm dort stehen sie gerne auf einem Bein, weil 
das ihre Standart ist ist das bei denen Standard

von peter (Gast)


Lesenswert?

Ardu ...au weia.....

Las es erstmal sein hier. Du verzettelst dich immer mehr.
Die Ausdrücke werden hier immer derber.

von Ardu (Gast)


Lesenswert?

Danke Falk, geniess dein Wochenende, soweit es möglich ist :) Komme erst 
heute Abend dazu das alles in die Tat umzusetzen, wenn ich nach der 
Spätschicht noch die Energie dazu hab.

@ Joachim

Na das kriegste aber gleich zurück: Afrika schreibt man in der deutschen 
Sprache mit "k". Nach "Stamm" muss ein Komma hin und danach "bei 
dem...", "...Standart ist" Komma "ist...". Und selbstverständlich gehört 
an das Ende eines Satzes ein Punkt. ;PPPP Das haste davon! Und nu zähl 
mal meine Fehler auf... wir schreiben uns in ein paar Tagen ;P

Das Display wird eben so in den meisten Fällen angeschlossen, egal, ob 
am LPT-Port oder am Mikrocontroller, da muss ein 
10müh-Fahrrad-Kondensator hin, daher ist es die Standart-Beschaltung.

von chris (Gast)


Lesenswert?


von Leuchte, die (Gast)


Lesenswert?

> liegt zwar auch daran, dass ich Visual Basic, HTML und Java
> gelernt habe,

  Aber weder Strukturierte/Modulare Programmierung noch sowas wie 
"Algorithmen & Datenstrukturen", wie an deinem Code ersichtlich.

  Erweiterungen wie z.B. Anzeigetexte in wählbarer Sprache verbockst Du 
Dir so.
1
const char[12][5] MONATE = {
2
    "Jan ",
3
    "Feb ",
4
    :
5
    "Dez "
6
};
7
8
void printMonth(const int month, const char[] lang)
9
{
10
      if((0 <= month) or (month <12))
11
         display.print(lang[month]);
12
      else
13
         display.print("--- ");
14
}
15
16
17
const char[7][5] WOCHENTAGE = {
18
    "Mon ",
19
    "Die ",
20
    :
21
    "Son "
22
};
23
24
void printDay(const int dayofweek, const char[] lang)
25
{
26
      if((0 <= dayofweek) or (dayofweek <7))
27
         display.print(lang[dayofweek]);
28
      else
29
         display.print("--- ");
30
}

  Legst Du dein Code beiseite und entdeckst z.B zum Jahresende (in 10 
Mte.) eine Fehlanzeige: wie findest Du anhand der Anzeige die passende 
Codestelle?

  Bisher ist Dein Code unwartbar.


  Du weisst dass deine Anzeige entweder 2x pro s (":" flasht In der 
Zeitanzeige, Sek.Zeiger springt) oder 6x pro s beim einstellen.
  --> schreibe eine möglichst einfache zeitgesteuerte Schleife welche 
EXAKT alle 1/6tel s durchläuft und nix anderes tut als:
 - entscheidet ob dieser Durchlauf übersprungen werden kann oder 
folgendes zu tun ist:
    - einen Buffer char[2][16] (oder wie gross auch immer dein Dosplay 
ist) zum LCD screibt
    - den Buffer m. " " (Leerschlag) kompl. füllt
    - neuen Bufferinhalt f. nächsten Durchlauf berechnet

  Erstmal ist nicht so wichtig wie und mit welcher genauigkeit die 
1/6tel s eingehalten werden (trödeln und Ticks zählen).
  Dies kann spaeter per zeitbasierten Interrupt geschehen. Noch spaeter 
kann auch Schalfmodus/Aufwecken dazukommen (wg. Stromsparen)

  Mach Dir ne Übersicht, welche Muster an Text char[2][16] (resp. Deine 
Displaygrösse) vorkommen:
1
//      0....5...10...15.
2
//  [0]"time  hh:mm WWW "
3
//  [1]"date  YYYY-MM-DD"
  In diesen "Masken" jeweils die Platzhalter durch die veränderlichen 
Werte ersetzen.
  Beim neubefüllen des Buffer, in einem Schlonz das Zeugs rüberkopieren 
(memcpy() oder so).

  Tritt nun ein Anzeigefehler auf, lässt sich die zugehörige Codestelle 
mit der ähnlichsten Maske/Muster sehr direkt auffinden.


PS: man verzeihe mir ev. C-Syntaxverletzungen, es geht mir um bessere 
Programmarchitektur. Syntax wird vom Compiler geschiedsrichtert.

von Leuchte, die (Gast)


Lesenswert?

PPS: ja, das lässt sich auch mit Arduino machen (google findet auch 
Beispiele f. einfache Echtzeitaudioeffekte auf Arduino basis)

von Ardu (Gast)


Lesenswert?

Leuchte: Wie erwähnt ist das nicht mein Code, sondern die Basis von 
meinem, der mittlerweile stark abgeändert ist. U.A. ist da nichts mehr 
mit Datum, hab alles so weit abgespeckt, dass ich im Grunde eine Uhr mit 
zwei Weckern und einem Menü habe, das ist kein Projekt, sondern Lernen, 
bis auf das erwähnte "flash"en ist nichts mehr in dem Code, das ich 
nicht verstehe, bzw. verstehe ich das jetzt dank Falk, aber es wird 
ebenso entfernt und die empfohlene Methode angewendet. Mir ist klar, 
dass solche Dinge wie Datum schon deutlich komplexer sind, daher ist das 
alles weg, auch Zeichnungen mit der Adafruit_GFX Bibliothek, wobei diese 
leicht zu verstehen ist, aber einfach im Moment unnötig.

von Joachim B. (jar)


Lesenswert?

Ardu schrieb:
> @ Joachim
>
> Na das kriegste aber gleich zurück: Afrika....

hast du Zitat verstanden? :p

von Ardu (Gast)


Lesenswert?

Entschuldige Leuchte, hab den Rest erst garnicht wahr genommen, hatte 
den originalen Code eigentlich gepostet, weil ich Verwirrungen vermeiden 
wollte, hab sie aber erst dadurch ausgelöst. Am besten ist, wenn ich 
meinen vervollständige und dann hier anhänge. Ich nutze die 
Adafruit_PCD8544 Bibliothek, die hat einen Buffer,hab mich noch nicht 
damit beschäftigt wie ich den nutzen soll, wenn es besser ist, hänge ich 
das ganze Projekt dran, mit allen Bibliotheken, da bitte bescheid sagen. 
Wenn mein Code hier steht, kannst du mir ja auszugsweise Beispiele 
zeigen, wie genau du das meinst, da würde ich mir überaus freuen.

Finde es auch super, dass du die Wartbarkeit so in den Fordergrund 
stellst, weil das auf jeden Fall gegeben sein muss, so will ich das auch 
von Anfang an umsetzen, egal, ob Basteleien oder ernste Projekte.

LG

von Ardu (Gast)


Lesenswert?

@Joachim

Ja xD Muss aber zugeben, nen Moment hats gebraucht Stand-Art, die Art zu 
stehen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.