Setting two alarms through an app using bluetooth?

Hi, complete beginner here, I am trying to create a sunrise alarm based off this tutorial:

However, I would like to set 2 alarm times instead of one. How would I modify the app and the code in order to do so?

Code:
/*
 Sjors Platjouw
 Arduino ITTT
 Sunrise Alarm clock with LCD Display and Bluetooth app
 */
#include <Wire.h> //De library voor I2C
#include <RTClib.h> //De library voor de klok
#include <LiquidCrystal_I2C.h> //De library voor het I2C scherm
 
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
#include <DS3231.h> //Include the clock library

// Changable Vars
int fadeTime = 1; // How long the light will fade to max
int setHour = 02; // Set hours to wake (military time)
int setMin = 49; // Set minute to wake 
int uled = 9; // Set pinout with PWM

// Set up Vars
RTC_DS1307 RTC; //Definieer de klok als DS1307

DS3231  rtc(SDA, SCL);
Time t;
void start();
 void start()
{
  // Fix for SB LED
  analogWrite(uled, 1);
  delay((fadeTime * 60000)/50); // fade timers
  analogWrite(uled, 2);
  delay((fadeTime * 60000)/50);
  analogWrite(uled, 3);
  delay((fadeTime * 60000)/50);
  analogWrite(uled, 4);
  delay((fadeTime * 60000)/50);
  analogWrite(uled, 4);
  delay((fadeTime * 60000)/50);
  analogWrite(uled, 5);
  delay((fadeTime * 60000)/50);


  // Fade script for the LED
  for (int i = 6 ; i <= 255; i++)
  {
    analogWrite(uled, i);
    delay(((fadeTime * 60000)/306));
//    Serial.print(" mil sec ");
//    Serial.print(((fadeTime * 60000)/306));
//    Serial.print(" PWM " );
//    Serial.print(i);


  }
  
  delay(20000); // Stay Bright
  analogWrite(uled, 0); // Turn off
  
}
void setup()
{
  Wire.begin();
  pinMode(uled, OUTPUT); // Set pinmode
  Serial.begin(9600); // Match to serial monitor
  RTC.begin();
  rtc.begin();
  
  lcd.backlight();
  lcd.begin(16, 2);
// uncomment these lines to set time, then reupload again without them.
//  rtc.setDOW(THURSDAY);     // Set Day-of-Week to SUNDAY
//  rtc.setTime(02, 10, 0);     // Set the time to 12:00:00 (24hr format)
//  rtc.setDate(17, 1, 2019);   // Set the date to January 1st, 2014
}

void loop()
{
  String input = "";
  while(Serial.available())
  {
    input += (char)Serial.read();
    delay(5);
  }
  DateTime now = RTC.now();
  lcd.setCursor(13,0); // Set text at 3,1 on display
  char dateBuffer[12]; // Set databuffer
  t = rtc.getTime(); // Make a time class called 't'
  
  // Send Day-of-Week
//  Serial.print(rtc.getDOWStr());
  lcd.print(rtc.getDOWStr());
  
  // Send date
//  Serial.print(rtc.getDateStr());
 lcd.setCursor(0,2);
  lcd.print(rtc.getDateStr());
 
  //sprintf(dateBuffer,"%02u-%02u-%02u ",now.day(),now.month(),now.year());

  // Send time
//  Serial.println(rtc.getTimeStr());
lcd.setCursor(0,0);
lcd.print(rtc.getTimeStr());
  
    delay(1000); //Wacht 1 seconde (1000 milliseconden)

lcd.setCursor(3,0);
  String firstHalf = getValue(input, ':', 0); // check first input untill ":"
  String secondHalf = getValue(input, ':', 1); // check second input after ":"

// use this code if you're not using the bluetooth module
//  //if (t.hour == setHour && t.min == setMin) // Check if it's time to wake up!
//  {
//    start();
//  }

// check first 2 digits inputs, then check second 2 digits of input
  if (t.hour == firstHalf.toInt() && t.min == secondHalf.toInt())
  {
    start();
  }
  
}

// logic to seperate strings
String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

App:


app screenshots - Album on Imgur (screenshot of the app ui, apologies for the link as I can only post one embedded image currently)

The alarm (which I assume is coded in the start function) seems to be set via a string of the form hh:mm, which is transmitted over serial.

You could try to extend this string to have two alarm times, e.g., hh:mm:hh:mm, which you can then read using the getValue function as follows.

// This is added to the end of `loop`.
firstHalf = getValue(input, ':', 3);
secondHalf = getValue(input, ':', 4);
if (t.hour == firstHalf.toInt() && t.min == secondHalf.toInt()) {
  start();
}
1 Like

@jfjlaros thank you for your help, I have tried it out and it did work, but is there a way to set 2 different alarms as different inputs such that in the app, i would have something that looks like this?

Again, thank you for your help, I really do appreciate it :slight_smile:

Both alarms should be set at the same time for the suggestion in post #2 to work, so I would use one input box.

E.g., to set alarm 1 to 8:30 and alarm 2 to 9:00, this should be sent.

08:30:09:00

[edit]

By the way, if your issue is solved, can you please mark the most helpful post as the solution? This prevents helpers spending time on a solved issue and it will lead people with the same question to the correct answer directly.

1 Like

Ahh so there is no way to use 2 input boxes and get 2 different alarms?

Also, could I send something like
08:30,09:00 instead? How would I have to change the code then?

Sure there is, but it would require some more changes.

I have little knowledge about that app thingy, but if is is possible to assign an ID to each input box, then I can propose some changes. Ideally, to set the first alarm, input box 1 should send string:

0:08:30

and to set the second alarm, input box 2 should send:

1:09:00

[edit]

To do something like this, replace the following (unused code),

with:

uint8_t alarm[][2] = {{0, 0}, {0, 0}};

After this block,

add the following lines to set the different alarms:

if (input.length()) {
  char* line = const_cast<char*>(input.c_str());
  uint8_t id = strtol(line, &line, 10);
  alarm[id][0] = strtol(line + 1, &line, 10);
  alarm[id][1] = strtol(line + 1, &line, 10);
}

To sound the alarms, replace the following block,

with:

for (uint8_t const (&alm)[2]: alarm) {
  if (t.hour == alm[0] and t.min == alm[1]) {
    start();
  }
}

You can get rid of the getValue function after this.

[edit2] Please note that I have modified the code examples above, I removed the dependency on the Time class because I could not find its definition.

1 Like

I see, thank you for the advice!
A few questions,

  1. Why does input box 2 send 1:09:00, not 0:09:00?
  2. What IDs should I assign to the input boxes?
  3. When I compile the code, it shows me this error message:
C:\Users\PC\AppData\Local\Temp\arduino_modified_sketch_151587\sketch_sep09c.ino: In function 'void loop()':
C:\Users\PC\AppData\Local\Temp\arduino_modified_sketch_151587\sketch_sep09c.ino:35:27: warning: invalid conversion from 'const char*' to 'char*' [-fpermissive]
   char* line = input.c_str();

How do I get rid of this?

  1. The alarm format is: id:hh:mm. Input box 1 has id 0 and input box 2 has id 1, so to set alarm 1 to 8:30, we send 0:08:30 and to set alarm 2 to 9:00, we send 1:09:00.
  2. 0 and 1.
  3. The char* should be a char const*. I fixed this in post #6.
1 Like

Hi, sorry if this is turning into a troubleshooting session, but after changing char* to char const*, these error messages pop up:

C:\Users\PC\AppData\Local\Temp\arduino_modified_sketch_214141\sketch_sep09c.ino: In function 'void loop()':
C:\Users\PC\AppData\Local\Temp\arduino_modified_sketch_214141\sketch_sep09c.ino:36:29: warning: invalid conversion from 'const char**' to 'char**' [-fpermissive]
   uint8_t id = strtol(line, &line, 10);
                             ^~~~~
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:23:0,
                 from sketch\sketch_sep09c.ino.cpp:1:
c:\program files (x86)\arduino\hardware\tools\avr\avr\include\stdlib.h:218:13: note:   initializing argument 2 of 'long int strtol(const char*, char**, int)'
 extern long strtol(const char *__nptr, char **__endptr, int __base);
             ^~~~~~
C:\Users\PC\AppData\Local\Temp\arduino_modified_sketch_214141\sketch_sep09c.ino:37:35: warning: invalid conversion from 'const char**' to 'char**' [-fpermissive]
   alarm[id][0] = strtol(line + 1, &line, 10);
                                   ^~~~~
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:23:0,
                 from sketch\sketch_sep09c.ino.cpp:1:
c:\program files (x86)\arduino\hardware\tools\avr\avr\include\stdlib.h:218:13: note:   initializing argument 2 of 'long int strtol(const char*, char**, int)'
 extern long strtol(const char *__nptr, char **__endptr, int __base);
             ^~~~~~
C:\Users\PC\AppData\Local\Temp\arduino_modified_sketch_214141\sketch_sep09c.ino:38:35: warning: invalid conversion from 'const char**' to 'char**' [-fpermissive]
   alarm[id][1] = strtol(line + 1, &line, 10);
                                   ^~~~~
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:23:0,
                 from sketch\sketch_sep09c.ino.cpp:1:
c:\program files (x86)\arduino\hardware\tools\avr\avr\include\stdlib.h:218:13: note:   initializing argument 2 of 'long int strtol(const char*, char**, int)'
 extern long strtol(const char *__nptr, char **__endptr, int __base);
             ^~~~~~

How can these errors be resolved? Again, sincerely thank you for doing so much :slight_smile:

Ah, my mistake. I thought your previous problem was an error, not a warning.

See the edited post #6 (again).

1 Like

Thank you so much, I think that part should work now. One last question, how would I modify your code such that the 2 different alarms would have two different alarm sounds instead of both being start()?

Just to clarify, I have the code for the 2 different alarm sounds, but I don't know how to separate the two alarms so that they each play their own sounds.

I would create a structure that contains the alarm settings and a callback function, e.g.,

struct Alarm {
  uint8_t hour;
  uint8_t minute;
  void (* const function)();
};

The current alarm array can then be replaced by an array of Alarm objects, which can be used as follows.

for (Alarm const& alm: alarm) {
  if (t.hour == alm.hour and t.min == alm.min) {
    alm.function();
  }
}

I have put all of these ideas in a simulator:

Thanks for the code! I haven't got the chance to process it yet, but I'll look through it carefully. Just a quick question, is it compatible with bluetooth & the alarm-setting app?

If the only thing the app does is sending a string of the form id:hh:mm, then it should be compatible.

Apologies, I have looked through the code to try and understand it, but I don't understand where I am supposed to put my alarm sound code. Could you give guidance on that?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.