Need help to finish the code

Hi. Some of you may know me from my posts in Project Guidance and Programming Questions sections. I'm from Eastern Europe. Right now, I'm trying to finish a project. I've been working on it for quite some time now. The code is almost finished, but it needs a final touch.

For me, it has gotten to a point where I feel it is more trouble than it is worth to try and fix it myself. I'm not very knowledgeable about programming and I have been able to get this far only thanks to numerous inputs from folks in Programming section.

I run a local carpet and souvenir shop that specializes mostly in antique items. I am prepared to trade a nice carpet for a little help with my code.

I need 3 things done:

Task number 1. I have various functions included in my loop. Two of them are specialEffects() and playAlarm(). specialEffects() plays at every hour sharp (00:00:00) and playAlarm is the alarmclock. playAlarm plays if hour, minute and second equal that of alarm time.
I want to make it so that if alarm time and specialEffects time coincide, only alarm will play.

Task number 2. Currently, my music sketch embodies a lot of delay() functions so cancel alarm button input is blocked. Hopefully, clear that issue. I am willing to change to another music, if a good enough music tone is suggested.

Task number 3. If I'm setting time with hour/minute buttons, and the hours become sharp in the process, I don't want the specialEffects to play. The reason I want it is that, my "set hour/set minute" buttons have both been programmed to reset seconds with each press, which I'd like to keep.

The problem is, if the minutes are equal to 00, and if I'm setting hours with "set hour" button, with every press, the seconds are reset also, so the condition 00min:00sec becomes true every time I press the set hour button. That is why I would like to make it so that if I'm in the process of setting time with min/hour buttons, the specialEffects won't play at all.

Forget the 3 seconds thing which I mentioned in programming section.

If anyone is interested, please let me know.

Anar.

sketch_dec27a.ino (23.3 KB)

Task 3: set a flag indicating you're editing, and have your alarm function test for that flag. If it sees editInProgress == true, don't play the alarm.

Task 1: how long is the specialEffects? Any chance for playAlarm to want to start while specialEffects is running already?

Task 2 sounds like a bit of a chore - haven't looked at the code yet, it may add some complications. You're basically switching to a state machine.

wvmarle:
Task 3: set a flag indicating you're editing, and have your alarm function test for that flag. If it sees editInProgress == true, don't play the alarm.

Task 1: how long is the specialEffects? Any chance for playAlarm to want to start while specialEffects is running already?

Task 2 sounds like a bit of a chore - haven't looked at the code yet, it may add some complications. You're basically switching to a state machine.

Please don't torture me. I've had enough of trying to fix it. Get it done and get the carpet. I will post it by registered mail. How does that sound? :slight_smile:

As per your notes:

Task 3 NOTE: You are right. if I'm in the middle of setting time, play neither specialEffect nor the alarm. because it doesn't make sense to play Alarm if you are already awake and setting time. At least I want it this way.

Task 2 NOTE: You may not have to implement a state machine. Please check this link. This is the code that I used as a basis for my project. He managed to make the alarm cancellable without the state machine. The only reason it does not work now, is because I have introduced another music sketch and loads of delay functions and removed the 2 return functions.

Task 1 NOTE: specialEffects() is like 10-15 seconds. By the way, I have used no flag to make playAlarm() stop. The condition for playalarm() is to look for hh:mm:ss. so because of the seconds being a condition, it does not play for a full minute. So, with my current setup, because they are all placed inside void loop(), if both conditions become true, first the specialEffects() plays, and then playalarm() plays. Both of them are placed in loop section but specialEffects() is placed before playAlarm().

Just looked at your code, and task 2 is indeed a chore. That are the same LEDs as in the matrix defined at the beginning, right?

Why are those -1 values in that matrix? No LED connected there?

Much more simplification possible. E.g. this block:

    if (minuteUnit & 1) {
      digitalWrite(leds[3][3], HIGH);
    } else {
      digitalWrite(leds[3][3], LOW);
    }
    if (minuteUnit & 2) {
      digitalWrite(leds[2][3], HIGH);
    } else {
      digitalWrite(leds[2][3], LOW);
    }
    if (minuteUnit & 4) {
      digitalWrite(leds[1][3], HIGH);
    } else {
      digitalWrite(leds[1][3], LOW);
    }
    if (minuteUnit & 8) {
      digitalWrite(leds[0][3], HIGH);
    } else {
      digitalWrite(leds[0][3], LOW);
    }

can be done in a single line:

for (byte i=0; i < 4; i++) digitalWrite(leds[3 - i][3], minuteUnit & (1 << i));

Now if you reverse the values in the matrix, you can make it even simpler and prettier:

for (byte i=0; i < 4; i++) digitalWrite(leds[i][3], minuteUnit & (1 << i));

Anyway, going through the whole thing will take a few hours. Not tonight, it's way too late.

wvmarle:
Just looked at your code, and task 2 is indeed a chore. That are the same LEDs as in the matrix defined at the beginning, right?

Why are those -1 values in that matrix? No LED connected there?

Yes, -1 is where no LEDs are connected.

Sure, take your time. If you do this, pm me your postal shipping address. I think you will like what you get.

I would like to add another thing to that list. But it is not as important as the others. The ledsOnOffValue. That is the button to turn the leds on and off. Normally it works in clock mode and alarm mode because in that section of the code, there is no delays. But I want that button to work and be able to turn the LEDs off also when the specialEffects() is playing. if you can do this too, it would be fantastic. if not, it is not as important.

Cheers.

Several questions/issues.

Which DS3231 library do you use? I tried a few, failed to get the sketch to compile, now simply commented out all the rtc code to at least be able to compile the thing. Of course I can't do actual testing but it at least takes care of most typos.

You define some buttons at the same pin numbers as the LEDs. Very confusing - turns out this are analog pins. I changed those to the A0 ~ A3 for less confusion.

The buttons can also be read using a digitalRead rather than analogRead, you can just use them as if they are regular digital pins.

You use pin numbers 0 and 1 for LEDs. Those are also used by Serial communications, and as such best avoided unless you don't have other pins left. You still have some analog pins available (A6, A7, A8 - not broken out in all Arduinos, at least the Pro Micro has them all).

I've added convenience functions to switch all LEDs on and off together.

In the alarm code of the readButtons() function are these three lines:

        hourAlarm = 22;
        minuteAlarm = 59;
        secondAlarm = 0;

what's the purpose?

I found two major blocking pieces of code: playAlarm() (in conjunction with sing() and buzz()), and specialEffects().
The easiest way to interrupt these is by connecting a push button to an interrupt. Then when the button is pressed, the interrupt is triggered which sets a flag. It's quite straightforward to have those functions check for this flag and stop when the flag is set.

For this you will have to change your wiring a bit (don't worry, I fixed the code to make that easy to implement) and connect the alarm stop button to pin 2 or 3, to allow it to use an external interrupt. Otherwise we'll have to use the slightly more complicated pin change interrupt for this.

I'm not too sure on the function of your buttons, so made a wild guess by attaching the interrupt to buttonAlarm. This is in setup(). Change this to the correct button, and then connect that button to digital pin 2 or 3 (for ATmega328 based Arduinos). It is set to trigger when the button falls, so that's for active LOW wired buttons.

The delay functions in both the playAlarm() and specialEffects() have been replaced by a milis() timer that checks for the interrupt flag. This did add some 4 kB to the compiled code, oh well, saved a lot elsewhere.

You'll see in specialEffects() that I changed all the digitalWrite() calls with a pattern based function. Now you can much easier and more visually set the patterns you want.

Hope it all works as intended and that I didn't introduce any new bugs - if not let me know what happens, and I'll have a look at what's wrong.

arduinoware_sketch.ino (39.2 KB)

wvmarle:
Several questions/issues.

Which DS3231 library do you use? I tried a few, failed to get the sketch to compile, now simply commented out all the rtc code to at least be able to compile the thing. Of course I can't do actual testing but it at least takes care of most typos.

You define some buttons at the same pin numbers as the LEDs. Very confusing - turns out this are analog pins. I changed those to the A0 ~ A3 for less confusion.

The buttons can also be read using a digitalRead rather than analogRead, you can just use them as if they are regular digital pins.

You use pin numbers 0 and 1 for LEDs. Those are also used by Serial communications, and as such best avoided unless you don't have other pins left. You still have some analog pins available (A6, A7, A8 - not broken out in all Arduinos, at least the Pro Micro has them all).

I've added convenience functions to switch all LEDs on and off together.

In the alarm code of the readButtons() function are these three lines:

        hourAlarm = 22;

minuteAlarm = 59;
        secondAlarm = 0;



what's the purpose?


I found two major blocking pieces of code: playAlarm() (in conjunction with sing() and buzz()), and specialEffects().
The easiest way to interrupt these is by connecting a push button to an interrupt. Then when the button is pressed, the interrupt is triggered which sets a flag. It's quite straightforward to have those functions check for this flag and stop when the flag is set.

For this you will have to change your wiring a bit (don't worry, I fixed the code to make that easy to implement) and connect the alarm stop button to pin 2 or 3, to allow it to use an external interrupt. Otherwise we'll have to use the slightly more complicated pin change interrupt for this.

I'm not too sure on the function of your buttons, so made a wild guess by attaching the interrupt to buttonAlarm. This is in setup(). Change this to the correct button, and then connect that button to digital pin 2 or 3 (for ATmega328 based Arduinos). It is set to trigger when the button falls, so that's for active LOW wired buttons.

The delay functions in both the playAlarm() and specialEffects() have been replaced by a milis() timer that checks for the interrupt flag. This did add some 4 kB to the compiled code, oh well, saved a lot elsewhere.

You'll see in specialEffects() that I changed all the digitalWrite() calls with a pattern based function. Now you can much easier and more visually set the patterns you want.

Hope it all works as intended and that I didn't introduce any new bugs - if not let me know what happens, and I'll have a look at what's wrong.

Thanks a lot.

OK, I will try to answer all the questions as best as I can.

NOTE 1.

Regarding the RTC library, this is the one I chose to use. I really like this one. If you changed the code to use another library, I'm really hoping that you can put it back. Please do if you can.

NOTE 2.

Regarding the following code:

 hourAlarm = 22;
 minuteAlarm = 59;
 secondAlarm = 0;

I'm glad you asked this because I was going to mention that. The reason I set the Alarm Time for 22:59 is that in the original code, no matter what I did, when the alarm first got turned on, it was going to 01:01. I could not get it to set to 00:00 to start with. I think this was down to the fact that the alarm itself is turned on using "set hour/set minute" buttons.

So, when it was first turning on, it was also adding 1 hour and 1 minute to the alarm time. At least, that is what I thought was happening. So, setting time to 22:59, gave me 00:00 when alarm was first turned on. Can you please change it to be 00:00 when alarm is first turned on, but in a more civilized way? :slight_smile:

NOTE 3.

Can you please explain in more detail, what I need to change with wiring? I am a bit confused about that. About the buttonAlarm, you have guessed right. I was originally using that button to switch between clock and alarm modes but also to cancel the alarm if it is playing. But I'm not too sure about wiring changes that I must do. Do you mean to connect the buttonAlarm to analog pin 2? It is already connected to that pin. Or if you mean to connect to digital pin, then where does the LED go (which is connected to that pin now)?

Originally my buttons were as follows:
buttonHour goes to A0: to set hours.
buttonMinute goes to A1: to set minutes.
buttonAlarm goes to A2: to switch between alarmmode and clockmode. also to cancel alarm if playing
buttonOnOff goes to A3. to toggle LEDs on and off.

A4 and A5 were used for RTC.

OK, will do a test now, to see if all is OK. Please check my NOTE 1 above and please put the original library back if you can. Thanks man! I'm so happy you are helping me. Also please check my PM.

Cheers.

arduinoware:
Regarding the RTC library, this is the one I chose to use. I really like this one. If you changed the code to use another library, I'm really hoping that you can put it back. Please do if you can.

Didn't touch it beyond commenting out the lines (and restoring them later - hopefully all).

NOTE 2.

Regarding the following code:

 hourAlarm = 22;

minuteAlarm = 59;
secondAlarm = 0;



I'm glad you asked this because I was going to mention that. The reason I set the Alarm Time for 22:59 is that in the original code, no matter what I did, when the alarm first got turned on, it was going to 01:01. I could not get it to set to 00:00 to start with. I think this was down to the fact that the alarm itself is turned on using "set hour/set minute" buttons. 

So, when it was first turning on, it was also adding 1 hour and 1 minute to the alarm time. At least, that is what I thought was happening. So, setting time to 22:59, gave me 00:00 when alarm was first turned on. Can you please change it to be 00:00 when alarm is first turned on, but in a more civilized way? :)

Gonna be tricky without test bed. I have to have a look at it.

It also shows that when the minutes roll over, the hour is increased. Is that your intended behaviour for setting the clock?

The intended working of the buttons is also a bit of a mystery to me.

Originally my buttons were as follows:
buttonHour goes to A0: to set hours.
buttonMinute goes to A1: to set minutes.

That works at all times? So whenever you press buttonHour the hour is increased by 1? Same for the buttonMinute? I'm a bit confused with this.

buttonAlarm goes to A2: to switch between alarmmode and clockmode. also to cancel alarm if playing

What are "alarmmode" and "clockmode", really?

buttonOnOff goes to A3. to toggle LEDs on and off.

That I pretty much figured.

For those buttons, best you give me a description of their intended behaviour. I have the feeling some more improvements can be made here.

Have you had a chance to install it on your clock again? Mostly hoping I didn't mess up the special effects and so.

wvmarle:
Didn't touch it beyond commenting out the lines (and restoring them later - hopefully all).

Gonna be tricky without test bed. I have to have a look at it.

It also shows that when the minutes roll over, the hour is increased. Is that your intended behaviour for setting the clock?

The intended working of the buttons is also a bit of a mystery to me.
That works at all times? So whenever you press buttonHour the hour is increased by 1? Same for the buttonMinute? I'm a bit confused with this.

What are "alarmmode" and "clockmode", really?

That I pretty much figured.

For those buttons, best you give me a description of their intended behaviour. I have the feeling some more improvements can be made here.

Have you had a chance to install it on your clock again? Mostly hoping I didn't mess up the special effects and so.

Hi. OK, sure, I will give your their description now:

  • So, about buttonMinute and buttonHour. They always work the same way. to set minutes and hours. And only that. In clock mode and in alarm mode. As per increasing the hour by 1, if the minutes roll over. Yes, it was indeed my intention which I'd like to keep if possible. So, I was intending to make it so that, you set minutes with "buttonMinute" and hours with "buttonHour". If minutes roll over, increase the hour also. if hour is 24, reset everything to 0. I like how the time setting buttons worked. You think we do it another way? Please explain in more detail if you can.

  • The clock was intended to have 2 modes. 1. Clock mode. 2. alarm mode. Clock mode is for showing time in binary coded decimal format. hh:mm. Alarm mode is for setting alarm time. You switch modes with buttonAlarm. So, for example, when the clock is first powered on, you are automatically in clock mode. And alarm is off by default.

If you want to set alarmtime, you press buttonAlarm once and it moves you from Clock mode to alarm mode. So you are in alarm mode now but alarm is not active yet. to set and activate alarm you press hour/min buttons together. Now, you are in alarm mode and alarm is active and you can set alarm time. when done setting alarm time you just click the buttonAlarm again, and this time it takes you back to clock mode.

so, to summerize, buttonAlarm takes you between modes (clock and alarm) and it acts like mode changing button. But it is also used to cancel the alarm. If the alarm is playing, and if you press the buttonAlarm, it cancels the alarm and deactivates the alarm. it was anyway, in the old code.

And in alarm mode, pressing hour/min together activates and deactivates the alarm.

TEST RESULTS SO FAR:

I looked at the code. I like the changes you've made so far. Especially the visual pattern editting capability in specialEffects() function. Unfortunately, I was not able to do any testing. Because for some reason the code is not working. I ran the code as is, without any changes to the wiring. Because I'm not entirely sure what exactly I need to change in wiring.

Please excuse my lack of knowledge. I have 4 buttons right now, do you mean to introduce a 5th button as an interrupter? or do you mean to connect buttonAlarm to interrupt pin which is digital pin 2 or 3?

So, there seem to be some outstanding issues. It would be nice if we could try and clear them. I really like the new code layout of yours and I certainly don't want to have to use the old code :slight_smile: The code is probably OK, could be that just a small thing needs to be changed. Anyway, below I have tried to summerize the issues that I can see. I was not able to do any deep testing of functions, clock and alarm modes etc. because I don't know what is going on with LEDs.

When I power up the clock, no matter how many times I press hour/minute buttons, the only LEDs that light up are the ones that correspond to 0, 1, 2 and 3 on the original LED layout matrix. But they light up erratically, not in any sequence that would make sense. Also, they don't light up normally. As I press the "set hour/set minute" buttons, those LEDs (0, 1, 2, 3 on matrix) sort of dim and flicker and do weird things. Never happened in old code. Could it be because I have not changed the wiring as you suggested?

I think at this point it is difficult to test other things, because the LEDs don't turn on the way they should. But I was able to make note of something. It is about specialEffects(). I was able to toggle through min/hour buttons and get the specialEffects() function to run (without visual indication of time on LEDs) and the specialEffects() actually ran OK, but it looks like it is still playing at every hour sharp even though you are in the process of setting time, which I don't want to happen. I want specialEffects() to play only if the hour becomes 00:00:00 naturally. So, in the process of setting time, I don't want this to happen.

  1. Also, as I mentioned in the main post, if specialEffects() and playAlarm() times coincide, I want only playAlarm() to play as priority and completely skip specialEffects().

  2. buttonOnOff seems to toggle LEDs on/off OK in normal modes. But when the specialEffects() is playing, it does nothing.

wvmarle:
Gonna be tricky without test bed. I have to have a look at it.

Please also see my reply above. if you need to see it, I will make a video and post the link here. Would that work?

Cheers.

That interrupt may get in the way now indeed. Uncomment the attachInterrupt line to disable that. I didn't move around any other pin numbers or so, no need to make changes. I'll also look into the pin change interrupt for the buttons as they are.

That's a long mail, going to read it better later.

wvmarle:
That interrupt may get in the way now indeed. Uncomment the attachInterrupt line to disable that. I didn't move around any other pin numbers or so, no need to make changes. I'll also look into the pin change interrupt for the buttons as they are.

That's a long mail, going to read it better later.

Hi did you get a chance to look at it?

Looking forward to hearing from you soon.

Not yet.

Got a few more projects on hand and today not feeling too well - my head got stuck with a bit of a cold, couldn't think well, and your project needs some serious thought plus some building (and both my Pro Micros are in use at the moment - maybe I should get one or two more of those, got a stack of NodeMCU boards but those are no use for this project). Really have to get this simulated here even though I don't have an RTC I should be able to do the rest.

wvmarle:
Not yet.

Got a few more projects on hand and today not feeling too well - my head got stuck with a bit of a cold, couldn't think well, and your project needs some serious thought plus some building (and both my Pro Micros are in use at the moment - maybe I should get one or two more of those, got a stack of NodeMCU boards but those are no use for this project). Really have to get this simulated here even though I don't have an RTC I should be able to do the rest.

Sure. No worries. Please let me know if you make any progress. How much time do you think we are looking at? Because this project is going to be a gift for my son. I am in divorce with his mother. I am only allowed to see my son so many times a year. So I am trying to get the timing right.

I will be looking forward to hearing from you. I hope you feel better soon.

Thank you.

Tomorrow I am posting what I promised in the PM. Also I will be adding to that package a nice set of handmade porcellain kitchen set for guests. I think you will appreciate that. It is good stuff.

Cheers.

After building the test set, to make it work: probably an hour or two. To make it work well, a day or two.

There appear to be issues with the buttons handling as well, I can't yet figure out how that's supposed to work. I'll anyway do my best to work with the existing wiring for that, should be able to make that work.

So there are four buttons: hour, minute, alarm and a general on/off. It seems that any press on hour/minute buttons will change the time, that doesn't sound like a good idea. So my suggestion:

  • long press (1 second or so) the on/off button goes in to time setting mode.
  • hour button advances the hour, rolling over at 23 back to 0.
  • pressing the minute button switches to minute setting; then pressing the button advances the minute, rolling over at 59 back to 0.
  • pressing the hour button goes back to hour setting, etc.
  • pressing the on/off button sets the time.

Same for the alarm button: long press goes into alarm setting mode.

Have the hour resp. minute LEDs flash as they are being set, so you know what you're doing (just no way to indicate whether you set alarm or time).

One alarm can be set (store in EEPROM to remember this over power cycles); rings for some time (how long?) until the alarm button is pressed.

Any way to entirely disable the alarm? Any way to indicate that the alarm is active or not?

wvmarle:
After building the test set, to make it work: probably an hour or two. To make it work well, a day or two.

There appear to be issues with the buttons handling as well, I can't yet figure out how that's supposed to work. I'll anyway do my best to work with the existing wiring for that, should be able to make that work.

So there are four buttons: hour, minute, alarm and a general on/off. It seems that any press on hour/minute buttons will change the time, that doesn't sound like a good idea. So my suggestion:

  • long press (1 second or so) the on/off button goes in to time setting mode.
  • hour button advances the hour, rolling over at 23 back to 0.
  • pressing the minute button switches to minute setting; then pressing the button advances the minute, rolling over at 59 back to 0.
  • pressing the hour button goes back to hour setting, etc.
  • pressing the on/off button sets the time.

Same for the alarm button: long press goes into alarm setting mode.

Have the hour resp. minute LEDs flash as they are being set, so you know what you're doing (just no way to indicate whether you set alarm or time).

One alarm can be set (store in EEPROM to remember this over power cycles); rings for some time (how long?) until the alarm button is pressed.

Any way to entirely disable the alarm? Any way to indicate that the alarm is active or not?

Hi. How are you?

Your stuff is on its way. I posted them today. I appreciate your help. Please keep it up. I will send you another special gift (surpize) when I see that the code is complete.

Just some update. Please read my comments below. I have tried to answer as many remarks as I can.

Regarding the weird issue on pin 1 (Rx) that you mentioned in your recent message, no I didn't have any issues with with that old code of mine. Everything was working as intended. May be you mean the initial flickering when arduino is first powered on, which I think is due to bootloader starting. But that is like a one time thing and then it gets to work and functions as intended. But probably you are referring to a different issue.

Regarding your latest comments on the forum, Yes, please do. I like all the new ideas which you mentioned in there, such as flashing when the clock or alarm is in setting mode and goes solid when it is back to normal mode. That sounds like a perfect idea.

He basically implemented everything so that, you click the buttonAlarm (acts like mode changing button) and then you are in alarm mode and you can activate alarm by pushing hour/minute buttons simultaneously (which turns on alarm clock) and you can set alarm time. Once alarm time is set, click buttonAlarm (which acts like mode change button) again, go to Clock mode and set the clock time, if needed. Simple as that.

In the old code, you would change between clock and alarm menus by simply pressing the buttonAlarm button as many times as needed to toggle back and forth between clock and alarm menus. And activate and deactivate alarm (only in alarm mode) by simulataneous press of hour/minute buttons. I hope it makes sense now. But if you have a better idea than this, please implement it. Thanks.

Please check this link:This was the original version of the code which I worked off from to make that old code of mine. The comments are in russian. It must have been written by a russian programmer. I found it online. But I think you will understand even without the comment.

I like your way of setting things a lot better. Although I was confused by some of your suggestions. Can you explain in more detail. I like the idea of flashing when in setting mode. Please implement the ideas which you mentioned in your recent reply. I was a little bit confused with long press suggestion.

Here is what my project looks like:

I am using 2 transistor setup for constant current supply. The right transistor is the main transistor through which the main current passes and lights up the LED. Both of the transistors in my case are 2N2222. When the current rises, some of the current is diverted to the base of the left transistor which in turn takes away some current from the base of the right transistor thus creating a feedback loop.

Cheers.

Also, forgot to mention, the general On/Off button, I was using that as a means of turning on and off the lights. But I think you are planning another use for that?

Just curious.

Cheers.

I know that LED circuit. A simple constant-current circuit.

For the testing I've set it up with simple LEDs, no transistors, just straight from the pin. The Rx needed its own resistor and is now happy. Clock is running after I got the order right, so that's progress.

Your buttons, are they active low (pull-up resistor) or active high (pull-down resistor)?

wvmarle:
I know that LED circuit. A simple constant-current circuit.

For the testing I've set it up with simple LEDs, no transistors, just straight from the pin. The Rx needed its own resistor and is now happy. Clock is running after I got the order right, so that's progress.

Your buttons, are they active low (pull-up resistor) or active high (pull-down resistor)?

Hi. My buttons are with pull-up resistor, so I think they are active LOW.

Cheers