Go Down

Topic: Need help to finish the code (Read 1 time) previous topic - next topic

arduinoware

Jan 08, 2018, 07:53 pm Last Edit: Jan 08, 2018, 08:08 pm by arduinoware
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.

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.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

arduinoware

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? :)

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().

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?

Much more simplification possible. E.g. this block:
Code: [Select]

    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:

Code: [Select]

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:
Code: [Select]

for (byte i=0; i < 4; i++) digitalWrite(leds[i][3], minuteUnit & (1 << i));
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

wvmarle

Anyway, going through the whole thing will take a few hours. Not tonight, it's way too late.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

arduinoware

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.

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:
Code: [Select]

        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.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

arduinoware

#7
Jan 09, 2018, 04:56 pm Last Edit: Jan 09, 2018, 05:45 pm by arduinoware
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:
Code: [Select]

        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:

Code: [Select]

 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? :)

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.

wvmarle

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).

Quote
NOTE 2.

Regarding the following code:

Code: [Select]

 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.

Quote
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.

Quote
buttonAlarm goes to A2: to switch between alarmmode and clockmode. also to cancel alarm if playing
What are "alarmmode" and "clockmode", really?

Quote
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.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

arduinoware

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 :) 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.

1.

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?

2.

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.

3. 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().

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

arduinoware

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.

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.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

arduinoware

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.

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.

Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

arduinoware

#14
Jan 10, 2018, 10:18 pm Last Edit: Jan 10, 2018, 10:22 pm by arduinoware
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.

Go Up