I am making a program that turns my lights on when I clap twice. I coded the project to:
1. listen for a noise (first clap)
2. listen for quiet (break between claps) this is to avoid false triggers (talking, etc.).
3. listen for a second noise (second clap).
The code runs through and works properly, but it has several breaking points that I am struggling to find/fix. I know if I make a noise, then I am quiet, then I make another noise repeatedly, and in rapid succession the code either gets stuck in the first while loop, or stops entering the first while loop altogether. The code often breaks when I am talking.
I have provided the code if anybody is willing to spare me some of there time and effort. I will be appreciative of all suggestions as I am still a beginner.
bool quiet = false;
bool loud = false;
int runtime = 1000;
int start = millis();
bool clap = false;
bool clap2 = false;
void setup() {
Serial.begin(9600);
pinMode(2, INPUT);
}
void loop() {
int mic = digitalRead(2);
if (mic == 0) {
Serial.println("loud");
clap = true;
} else {
Serial.println("quiet");
}
if (clap == true) {
clap = false;
Serial.println("clap");
start = millis();
delay(500);
while (start >= millis() - runtime && loud != true) {
mic = digitalRead(2);
if (mic == 0) {
Serial.println("noise detected!");
loud = true;
} else {
Serial.println("scilence");
quiet = true;
}
}
} else {
delay(1);
}
if (quiet == true && loud == false) {
quiet = false;
Serial.println("listening for second clap...");
delay(500);
start = millis();
while (start >= millis() - runtime) {
mic = digitalRead(2);
if (mic == 0) {
clap2 = true;
} else {
delay(1);
}
}
} else {
loud = false;
quiet = false;
}
if (clap2 == true) {
clap2 = false;
Serial.println("clap 2");
delay(1000);
} else {
delay(1);
}
}
Welcome to StackOverflow!
From the program you posted I think you are over-complicating it ;). First of all, the delay() function is a blocking function: nothing can happen during the lapse of time of the delay. Thus it is usually advise to compare times in order to know if you have waited enough: you can then perform other tasks in the meantime.
I would propose something like this for your loop() function:
if(digitalRead(2)==0) //loud
{
unsigned long first_clap_time = millis();
unsigned long elapsed_time = 0;
bool silence = false;
bool exit = false;
while (elapsed_time < 5000 || exit) // allow a max delay of 5sec
{
if (digitalRead(2)!=0) silence = true;
elapsed_time = millis() - first_clap_time;
if (digitalRead(2)==0 && elapsed_time > 500 && silence)
{
Serial.println("Two claps detected!"); //if a second clap is detected 500 milliseconds after the first, and before 5 sec, and a silence was detected
exit = true;
}
}
}
This should be able to detect only two claps, separated by a time between 500 milliseconds and 5 seconds (to adjust of course). I have no way to test this program so do not hesitate to provide feedback!
Hope it helps,
I want to be able to start off the program with nothing on, then when I push the button once, it should switch to red, then if you push it another time it should switch to green, and push it again and it should go to blue. After all that it should turn off when you push the button again, then it just loops.
Here's what I've been working with but it seems to fail.
When you push the button the first time it always goes to red, if you push it again, it does nothing. If you keep spamming the button it switches randomly through all the colors but never turns off.
void loop() {
int toRed = digitalRead(button);
if (toRed == HIGH){
switchtoRed();
delay(250); // Give you time to take your finger off the button.
int toGreen = digitalRead(button);
if (toGreen == HIGH) {
switchtoGreen();
delay(250);
int toBlue = digitalRead(button);
if (toBlue == HIGH) {
switchtoBlue();
delay(250);
int state = digitalRead(button);
if (state == HIGH) {
return;
}
}
}
}
}
The problem is the logic in your code is flawed. It is acting as if the digitalRead function is waiting until you press the button. Instead what is actually happening is the loop function is being called repeatedly and you're only ever really testing the outermost button test or if you spam the button, you might be lucky enough to get it to cycle through each of the colours.
Instead what you want is to just test the button and if has been pressed, increment a variable to indicate what light should be on. Something like:
int pressed = 0;
int state = 0;
void loop()
{
if(digitalRead(button)==HIGH)
{
if(pressed==0)
{
pressed=1;
switch(state)
{
case 0:
switchToRed();
state++;
break;
case 1:
switchToGreen();
state++;
break;
case 2:
switchToBlue();
state++;
break;
case 3:
switchToOff();
state=0;
break;
}
}
}
else
{
pressed=0;
}
}
You can do something like this with using a state machine design pattern approach:
int nextState = 0;
void loop(){
while(1){
if(digitalRead(button) == HIGH){
switch(nextState){
case 0: // Red Button
switchToRed();
break;
case 1: // Green Button
switchToGreen();
break;
case 2: // Blue Button
switchToBlue();
break;
case 3: // Switch off
switchOff();
break;
}
nextState = (nextState + 1) % 4;
delay(250);
}
// or you can delay here
}
}
And if you don't want to continue after case 3; you can break the loop using a return statement in case 3.
I started a project quite recently were I intend to combine the arduino uno and the sim808 module which has gps/gsm/gprs all together in one.
Using just the gps functionality works fine, just the gsm both receiving and sending messages also works good. but combining them for what i intend makes the entire system falls apart.
I intend to be able to have some coordinates registered let's say position A position B and position c, and the system i intend to design is put on a moving, let's say car, now anyone on either of the positions will send a message with the alphabet denoting the position to a number lets say "A TO +23*******98 , AND WOULD get a reply of the cars current time from that position.
With all parts combined the program would sometimes not even indicate receiving any message or even if it did the gps part won't even work.
Is there something I am doing wrong or is it not just feasible with what the components I am using pls help as I am very confused right now.
`#include <SoftwareSerial.h>
SoftwareSerial GPRS(7, 8); // RX, TX
String BUSNUM="A"; // THIS SIM IS TO BE INSTALLED ON BUS A
static String sendersnumber;
char* key;
char MESSAGE[280];
String latitude;
String longitude;
String Speed;
enum _parseState
{
PS_DETECT_MSG_TYPE,
PS_IGNORING_COMMAND_ECHO,
PS_READ_CMTI_STORAGE_TYPE,
PS_READ_CMTI_ID,
PS_DETECT_MSG_TYPE2,
PS_IGNORING_COMMAND_ECHO2,
PS_READ_CMGR_STATUS2,
PS_READ_CMGR_CONTENT2,
PS_READ_CMGR_DATE2,
PS_READ_CMGR_STATUS,
PS_READ_CMGR_NUMBER2,
PS_READ_CMGR_NUMBER,
PS_READ_CMGR_SOMETHING,
PS_READ_CMGR_DATE,
PS_READ_CMGR_CONTENT,
PS_READ_VIDEO_CONTENT,
PS_READ_VIDEO2_CONTENT,
PS_READ_CMGR_SOMETHING2,
PS_READ_VIDEO_CONTENT2,
};
byte state = PS_DETECT_MSG_TYPE; // KEEP TRACK OF WHAT STATE WE ARE IN RIGHT NOW
char buffer[100]; // WHAT WE ARE READING INTO
byte pos = 0; //WHAT POSITION WE ARE AT IN THAT BUFFER
int lastReceivedSMSId = 0; // LAST RECIEVED SMS ID
boolean validSender = false; //SOO NOT JUST ANYONE HAS ACESS TO SEND A COMMAND
void resetBuffer()
{
memset(buffer, 0, sizeof(buffer));
pos = 0;
}//BASICALLY TO RESET THE BUFFER
void setup()
{
GPRS.begin(9600);
Serial.begin(9600);
GPRS.println("AT+CGNSPWR=1");
delay(290);
GPRS.println("AT+CGNSURC=0");
delay(300);
GPRS.println("AT");
delay(300);
GPRS.println("AT+CMGF=1"); // INITIALIZE SMS
delay(300);
for (int i = 1; i <= 15; i++)
{
GPRS.print("AT+CMGD=");
GPRS.println(i);
delay(300);
// Not really necessary but prevents the serial monitor from dropping any input SINCE WE KNOW LIMIT TO STORE IS 15, THIS JUST DELETES IT CLEARS IT
while(GPRS.available())
Serial.write(GPRS.read());
}
delay(2000);
GPRS.println("AT+CGNSURC=1");
}
void loop()
{
while(GPRS.available()) //ONLY WHEN THERE IS SOMETHING AVAILABLE,
{
GSM_NUM1(GPRS.read());
//delay(50);
GPRS.println("AT+CGNSINF");
// delay(40);
GPSAnalyzer(GPRS.read());
sendSMS();
}
}
// END OF VOID LOOP
void GSM_NUM1(byte b)
{
buffer[pos++] = b;
if ( pos >= sizeof(buffer) )
resetBuffer(); // just to be safe
switch (state)
{
case PS_DETECT_MSG_TYPE:
{
if ( b == '\n' )
resetBuffer();
else {
if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) {
state = PS_IGNORING_COMMAND_ECHO;
}
else if ( pos == 6 ) {
//Serial.print("Checking message type: ");
//Serial.println(buffer);
if ( strcmp(buffer, "+CMTI:") == 0 ) {
Serial.println("Received CMTI");
state = PS_READ_CMTI_STORAGE_TYPE;
}
else if ( strcmp(buffer, "+CMGR:") == 0 ) {
Serial.println("Received CMGR");
state = PS_READ_CMGR_STATUS;
}
resetBuffer();
}
}
}
break;
case PS_IGNORING_COMMAND_ECHO:
{
if ( b == '\n' ) {
//Serial.print("Ignoring echo: ");
//Serial.println(buffer);
state = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_READ_CMTI_STORAGE_TYPE:
{
if ( b == ',' ) {
Serial.print("SMS storage is ");
Serial.println(buffer);
state = PS_READ_CMTI_ID;
resetBuffer();
}
}
break;
case PS_READ_CMTI_ID:
{
if ( b == '\n' ) {
lastReceivedSMSId = atoi(buffer);
Serial.print("SMS id is ");
Serial.println(lastReceivedSMSId);
GPRS.print("AT+CMGR=");
GPRS.println(lastReceivedSMSId);
//delay(500); don't do this!
state = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_READ_CMGR_STATUS:
{
if ( b == ',' ) {
Serial.print("CMGR status: ");
Serial.println(buffer);
state = PS_READ_CMGR_NUMBER;
resetBuffer();
}
}
break;
case PS_READ_CMGR_NUMBER:
{
if ( b == ',' ) {
Serial.print("CMGR MSSG SENDERS Number: ");
Serial.println(buffer);
String sendersnumber=buffer;
// Uncomment these two lines to check the sender's cell number
//validSender = false;
//if ( strcmp(buffer, "\"+0123456789\",") == 0 )
validSender = true;
state = PS_READ_CMGR_SOMETHING;
resetBuffer();
}
}
break;
case PS_READ_CMGR_SOMETHING:
{
if ( b == ',' ) {
Serial.print("CMGR something A.K.A SENDER'S NAME: ");
Serial.println(buffer);
state = PS_READ_CMGR_DATE;
resetBuffer();
}
}
break;
case PS_READ_CMGR_DATE:
{
if ( b == '\n' ) {
Serial.print("CMGR date: ");
Serial.println(buffer);
state = PS_READ_CMGR_CONTENT;
resetBuffer();
}
}
break;
case PS_READ_CMGR_CONTENT:
{
if ( b == '\n' ) {
Serial.print("CMGR MESSAGE Content: ");
Serial.print(buffer);
String key=buffer;
// sendSMS();
// GPSAnalyzer();
GPRS.print("AT+CMGD=");
GPRS.println(lastReceivedSMSId);
//delay(500); don't do this!
state = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
}
}
void GPSAnalyzer(byte b)
{
buffer[pos++] = b;
if ( pos >= sizeof(buffer) )
resetBuffer();// just to be safe
switch (state)
{
case PS_DETECT_MSG_TYPE2:
{
if ( b == '\n' )
resetBuffer();
else {
if ( pos == 9 ) {
// Serial.print("Checking message type: ");
// Serial.println(buffer);
if ( strcmp(buffer, "+UGNSINF:") == 0 ) {
Serial.println("Received CGNSINF:");
state = PS_READ_CMGR_STATUS2;
}
resetBuffer();
}
}
}
break;
//CHECK
case PS_IGNORING_COMMAND_ECHO2:
{
if ( b == '\n' ) {
//Serial.print("Ignoring echo: ");
//Serial.println(buffer);
state = PS_DETECT_MSG_TYPE2;
resetBuffer();
}
}
break;
//THIS WOULD READ FROM +CGNSINF: (TO THE COMMA),
case PS_READ_CMGR_STATUS2:
{
if ( b == ',' ) {
Serial.print("RUN STATUS: ");
Serial.println(buffer);
String runstatus=buffer;
state = PS_READ_CMGR_NUMBER2;
resetBuffer();
}
}
break;
case PS_READ_CMGR_NUMBER2:
{
if ( b == ',' ) {
Serial.print("FIX STATUS : ");
Serial.println(buffer);
String fixstatus=buffer;
fixstatus.replace(","," ");
validSender = true;
state = PS_READ_CMGR_SOMETHING2;
resetBuffer();
}
}
break;
// this is DATE AND TIME i dont need this
case PS_READ_CMGR_SOMETHING2:
{
if ( b == ',' ) {
Serial.print("DATE AND TIME : ");
Serial.println(buffer);
String dateandtime=buffer;
state = PS_READ_CMGR_DATE2;
resetBuffer();
}
}
break;
case PS_READ_CMGR_DATE2:
{
if ( b == ',' ) {
Serial.print("LATITUDE: ");
Serial.println(buffer);
latitude=buffer;
latitude.replace(","," ");
state = PS_READ_CMGR_CONTENT2;
resetBuffer();
}
}
break;
case PS_READ_CMGR_CONTENT2:
{
if ( b == ',' ) {
Serial.print("LONGITUDE: ");
Serial.println(buffer);
longitude=buffer;
longitude.replace(","," ");
state = PS_READ_VIDEO_CONTENT2;
resetBuffer();
//delay(500); don't do this!
}
}
break;
case PS_READ_VIDEO_CONTENT2:
{
if ( b == ',' ) {
Serial.print("ALTITUDE: ");
Serial.println(buffer);
String Altitude=buffer;
state = PS_READ_VIDEO2_CONTENT;
resetBuffer();
//delay(500); don't do this!
}
}
break;
case PS_READ_VIDEO2_CONTENT:
{
if ( b == ',' ) {
Serial.print("SPEED(KM/HR): ");
Serial.println(buffer);
String Speed=buffer;
Speed.replace(","," ");
state =PS_DETECT_MSG_TYPE2;
resetBuffer();
}
}
break;
//use goto to put it at sms begining
}
}
void sendSMS()
{
if ( strcmp(key,"A") == 0 )
{
float lati=7.200970;
float longi=5.181782;
float Speed1 = atof(Speed.c_str());
float latituded = atof(latitude.c_str());
float longituded = atof(longitude.c_str());
float Distance = HaverSine(lati,longi,latituded,longituded);
float duration=Distance/Speed1;
const int StrLen = 10;
char * duration_new ;
double Value = duration;
(void) dtostrf (Value, StrLen, 6, duration_new);
String MESSAGE="BUS A";
MESSAGE+=duration_new ;
Serial.print("THE MESSAGE SENT IS ");
Serial.println(MESSAGE);
}
else if ( strcmp(key,"B") == 0 )
{
float lati=7.290970;
float longi=5.141782;
float Speed1 = atof(Speed.c_str());
float latituded = atof(latitude.c_str());
float longituded = atof(longitude.c_str());
float Distance = HaverSine(lati,longi,latituded,longituded);
float duration=Distance/Speed1;
const int StrLen = 10;
char * duration_new ;
double Value = duration;
(void) dtostrf (Value, StrLen, 6, duration_new);
String MESSAGE="BUS B";
MESSAGE+=duration_new ;
Serial.print("THE MESSAGE SENT IS ");
Serial.println(MESSAGE);
}
delay(300);
GPRS.print("AT+CMGF=1\r\n");
delay(100);
GPRS.println("AT+CMGS=\""+sendersnumber+"\"\r\n");
delay(100);
GPRS.println(MESSAGE);
delay(100);
GPRS.println((char)26);
delay(100);
GPRS.println();
delay(100);
}
float HaverSine(float lat1,float lon1,float lat2,float lon2)
{
String fixstatus;
float ToRad = PI / 180.0;
float R = 6371; // radius earth in Km
float dLat = (lat2-lat1) * ToRad;
float dLon = (lon2-lon1) * ToRad;
float a = sin(dLat/2) * sin(dLat/2) +
cos(lat1 * ToRad) * cos(lat2 * ToRad) *
sin(dLon/2) * sin(dLon/2);
String o= fixstatus + "8";
float c = 2 * atan2(sqrt(a), sqrt(1-a));
float d = R * c;
return d;
}
EXPLANATION After all declarations and initializations the first active part of the entire code is the for loop that just deletes all former messages from the sim card memory.it runs 15 times
for (int i = 1; i <= 15; i++) { GPRS.print("AT+CMGD="); GPRS.println(i); delay(300); while(GPRS.available()) Serial.write(GPRS.read()); }
Now, having functions GSM_NUM1(); GPSAnalyzer(); sendSMS(); Which are defined below in the code
GSM_NUM1(); GPSAnalyzer(); both work similarly they extract needed data which come in separated by commas. For the gps which comes in , in the form
+UGNSINF: ,,,,, ,,, ,,,,,,, ,,,,
lathitude, speed and any other important parameter is extracted.
For GSM_NUM1(); it gets the senders message and number into variable.
sendSMS(); this just does some calculation based on the message received and send a certain result to the number who requested it.
OBERVATIONS
When the program starts nothing happens which is good cause nothing is supposed to until something new comes in. Hence the void loop() { while(GPRS.available()) //ONLY WHEN THERE IS SOMETHING AVAILABLE, { GSM_NUM1(GPRS.read());
//delay(50); GPRS.println("AT+CGNSINF"); // delay(40);
GPSAnalyzer(GPRS.read()); sendSMS(); } Now this is were things go bad, as the first function works good, it waits gets the message and extracts the senders number and message"key" into variables but immediately after that I wantjust one return of the gps info shown below that's why I used ("AT+CGNSINF"); instead of ("AT+CGNSURC=1"); as the later gives continuous gps data such as
+UGNSINF: ,,,,, ,,, ,,,,,,, ,,,,
BUT instead of one line of the gps data to be gotten from were lathitude and some other parameters are extracted into variables "THE PROGRAM HANGS/STOPS for some unknown reason.
SUSPICIONS
Since the SIM808 possess gps/gsm on the same module. It makes it kind of tricky to separate them in the sense that.
IF I WANT THE GPS TO BE ON BUT NOT READ IN ANY DATA UNTIL A VALID REQUEST COMES IN , IN FORM OF AN SMS THEN THE NECESSARY GPS INFORMATION IS PARSED AND SOME CALCULATIONS ARE DONE TO GET A PARAMETER THAT WOULD BE SENT TO THE SAME NUMBER THAT REQUESTED IT.
PERSONNALY, I FEEL THAT GETTING THE GPS AND GSM TO WORK HAND IN HAND WITHOUT CANCELLING EACH OTHER OUT IN SOME WAY,SUCESSFULLY WOULD BE THE END OF MY PROBLEM. AND I THINK IT COMES DOWN TO THE POSITION OF THE AT COMMAND
GPRS.println("AT+CGNSURC=1"); AND/OR GPRS.println("AT+CGNSINF"); AS the former spits out the gps data every GNSS FIX continuously when called once and LATER spits it out just once per one command.
the attached picture just shows the continous nature of the output of ("AT+CGNSURC=1"); , just as ("AT+CGNSINF"); spits out just one line with +CGNSINF: at the begining instead
Please check that is not in overflow SRAM , that produces stranger things when you execute the program. This occur when you declare so much variables, you can use this library to check the use of sram.
I ran into this similar issue with trying to get GPS data from a module over serial but figured it out after painstaking hours. Essentially you need to validate every response from every command and flush the serial port before every write.
Flushing the serial port buffer before you write any command will ensure that you don't accidentally read left over characters from a previous command when you are trying to get the output of the one you just ran. Most TAs (Terminal Adapters) use EOL characters like OK which translates into "\r\nOK\r\n". If you do not read them all, they can hang around and interfere with the next command you send/ read a response from.
use GPRS.flush() to get rid of extra garbage characters in the serial buffer before sending commands.
Also, creating a generic command function to pass all AT commands and validate their output will save you a lot of sleep.
something like
int sendCommand(int fd, char* message, char* eol, char* response){
int wlen, rlen;
char buf[1024];
tcflush(fd, TCIOFLUSH); //flush the serial port to remove anything left over
wlen = write(fd, message, strlen(message)); //write command to terminal
tcdrain(fd); //delay until 1st readable character is written by modem
delay(100); //delay a little longer until all characters are written(hopefully)
rdlen = read(fd, buf, sizeof(buf) - 1); //read from serial port
if(rdlen > 0){ //if readable characters
if(strstr(buf, eol) != NULL){ //if my end of line character is present then
int i = 0; //output from TA is complete
while(buf[i] != '\0'){ //while buffer has more characters
response[i] = buf[i]; //copy string into the string I passed, char by char
}
return 1; //return 1 (i.e.true aka success)
}
}
return 0; //return 0 (i.e. false aka failure)
}
I wrote this for a communicating to a simcom5320 but I didnt use software serial so it'll be a little different for you. Use this function for all your at commands to ensure everything actually succeed like:
char commandReply[512];
if(sendCommand(myFileDescriptor, "AT+CGNSINF\r", "\r\nOK\r\n", commandReply)){
//do something with commandReply or not
} else {
//command failed
//do something else
}
Hope this helps!
I made G-code reader on Arduino, but it stops reading. It has many "break;" and I have also many while loops and switches, so I'm thinking that when I break on loop/switch, it will break all.
Another idea is that it goes some kind of loop, but I can't figure out where it loops.
Here is my code:
void Gcode(){
String yy,xx,gg;
char text[64];
int number=1;
while(number!=3){
while (Serial.available()>0) {
delay(3); //delay to allow buffer to fill
char c = Serial.read();
Serial.println(c);
switch(c){
case 'G':
//read_number()
while (Serial.available()>0) {
char k = Serial.read();
if(k==' ' || k=='\n'){
break;
}
else{
gg+=k;
}
}
switch(gg.toInt()){
case 1:
Serial.println(gg);
while (Serial.available()>0) {
c = Serial.read();
Serial.println(c);
switch(c){
case 'X':
while (Serial.available()>0) {
char k = Serial.read();
if(k==' ' || k=='\n'){
break;
}
else{
xx+=k;
}
}
char buf[xx.length()];
xx.toCharArray(buf,xx.length());
x2=atof(buf);
Serial.println(x2);
break;
case 'Y':
while (Serial.available()>0) {
char k = Serial.read();
if(k==' ' || k=='\n'){
break;
}
else{
yy+=k;
}
}
Serial.println(yy);
char buf2[yy.length()];
yy.toCharArray(buf2,yy.length());
y2=atof(buf2);
break;
case 'E':
break;
case 'F':
break;
default:
Serial.print("the end");
}
Serial.print("out of switch");
}
break;
case 2:
break;
default:
Serial.print("nothing");
}
break;
case '\n':
number=3;
break;
default:
Serial.print("default");
}
}
}
if(sizeof(yy)>0){
yy="";
xx="";
gg="";
}
Serial.print("quit");
}
When I send G1 X10.00 Y-100.00 \n It prints only:
G
1
X
10.00
out of s
one of your big problem is that your while end when thwere are nomore carachter. This mean that if your loop consume the buffer FASTER than it get written (remeber:9600 baud mean 960Byte/s, arduino even if slow but can compute 16.000.000 operation/s...).
Another big problem MAY bethe lack of ram, os your output is truncated. there is some function to check real time usage of ram, see http://playground.arduino.cc/Code/AvailableMemory, stopping to use String and even char array is a way better idea; the code is not that hard to write!
so the pc would send "G1 X10.00 Y-100.00 \n"
but at time X your aruino get "G1 X10.00", if you read really fast the buffer now (faster than 1/960 of a second, arduino is a way faster than that!)
so ideally you should change all your while condition removing serial available but instead putting the condition you use in the if with the break; sothe first while from
while (Serial.available()>0)
became
while ( (k=Serial.read()) != ' ' && k != '\n') //yes it is a bit weird like this
maybe a little better, with check that k is a valid caracter, AND timeout
unsigned long timeout_ms = 1000; //timeout after 1 seconds from NOW!
unsigned long start_ms = millis();
int k=Serial.read();
while ( k != ' ' && millis()-start_ms < timeout_ms){// because here we expect "Gx ", why are you was also using k != '\n'? removed, feel free to add it back
if (k == -1){
k=Serial.read(); //read the next char
continue; //return to the beginning of the while
}
[... do thigs...]
k=Serial.read(); //read the next char
//here you may add "start_ms = millis();" if you want to reset the timeout
}
I'm having a problem with an if ladder and the for loops in each of them in this gameProcess function. Essentially the for loop in the (mode == 1) loop is not entered at all and I'm not sure why.
I think it's something to do with the positioning because if (mode == 1) is switched with (mode == 0), the (mode == 1) for loop will be entered but the (mode == 0) won't. Been stuck on this for a while and can't seem to spot what's up with the function. Any help would be greatly appreciated. Thanks.
// 5 means 10 switches as one iteration is a change between one mode to another, not on and off.
int gameProcess(int mode) {
Serial.println("> Starting game process.");
// 4 second delay between
int interval = 1000;
int initialDelay = 5000;
enter code here:
//delay(initialDelay);
if (mode == 1) {
// for a standard 25 round with a 2 sec interval
Serial.println("starting mode 1");
for (int i; i < 51; i++) {
Serial.println("In loop");
Serial.println(interval);
flickPin(13);
workingDelay(interval);
}
Serial.println("finished mode 1");
} else if (mode == 2) {
while(true) {
flickPin(13);
int minRandVal = 1000;
int maxRandVal = 15000;
int randomDelay = random(minRandVal, maxRandVal);
Serial.println(randomDelay);
workingDelay(randomDelay);
}
} else if (mode == 0) {
// for 10 rounds. Find out why it needs 35 and not 20.
Serial.println(" - Mode 0 .");
for (int i; i < 35; i++) {
Serial.println(interval);
flickPin(13);
workingDelay(interval);
}
Serial.println(" - finished Mode 0 .");
} else {
char error[80];
sprintf(error, "Unknown mode = %d", mode);
Serial.println(error);
}
}
Here is the main loop and the initializeGame function where the gameProcess function is called from.
int initializeGame(bool started, int mode) {
if (started == true) {
Serial.println(" -> in startMonitor, start button pressed");
Serial.println(mode);
gameProcess(mode);
// if the mode is 0 (none of the lights are on), that means it's in random mode and any interval between 5 and 60 secs come up until you stop it!
// set it back to false and turn the game light off because the game is over.
started = false;
digitalWrite(9, LOW);
} else {
started = false;
}
return started;
}
void loop()
{
// check if the pushbutton is pressed.
mode = stateMonitor(activeButton);
// now set the game mode led.
lightUpModeLed(ledPins[mode]);
// now check to see if the game has been initialized.
started = startMonitor(startButton, ledPins[4], started);
// read the state of the pushbutton value:
// initialize game if it hasn't already started.
// TODO this is where the loop will likely spend the majority of it's time so how can this be
started = initializeGame(started, mode);
saveData();
}
if you are using windows then install Atmel Studio and the Visual Micro Plugin then you can debug and watch what the code is doing and the values of variables.
This will take away the mystery, which it did for me.