Turning logging on and off with push button...

I am trying to turn SD logging on and off with a push button… I am displaying values on an LCD screen and then want to be able to log the values by pressing a button and then turn off the logging by pressing a button. I have the values displaying to a screen but when I trigger the logging function, the screen locks up and no logging is actually done either. Everything seems to just lock.

The switch function is:
void loggerbutton(){

logtemp = logger;
if (logtemp == 0)
logger = 1;
if (logtemp == 1)
logger = 0;

switch(logger){
case 0:
//log button
myGLCD.setColor(255, 0, 0);
myGLCD.fillRoundRect(183, 0, 284, 119); //top log box
myGLCD.setBackColor(255, 0, 0);
myGLCD.setColor(0, 0, 0);
myGLCD.print(“LOG”, 208, 60);
myGLCD.print(“Off”, 208, 75);
break;
case 1:
loggerinit();
//log button
myGLCD.setColor(0, 255, 0);
myGLCD.fillRoundRect(183, 0, 284, 119); //top log box
myGLCD.setBackColor(0, 255, 0);
myGLCD.setColor(0, 0, 0);
myGLCD.print(“LOG”, 208, 60);
myGLCD.print(“On”, 208, 75);
break;
default:
break;
}
}

The logger function (abbreviated) is:

void loggerinit()
{

// initialize the SD card
if (!card.init()) error(“card.init”);
// initialize a FAT volume
if (!volume.init(card)) error(“volume.init”);
// open root directory
if (!root.openRoot(volume)) error(“openRoot”);
// create a new file
char name = “LOGGER00.CSV”;
for (uint8_t i = 0; i < 100; i++) {
name[6] = i/10 + ‘0’;
name[7] = i%10 + ‘0’;
if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;
}
if (!file.isOpen()) error (“file.create”);

// write header
file.writeError = 0;
file.println(“time,lat,long,speed,date,xA,xE,yA,yE,zA,zE,lean,leane,dive,dive_e,T1mp,RPM,V,TPS,Frt,Rear,AFR,Fork,shock”);

// attempt to write out the header to the file
if (file.writeError || !file.sync()) {
error(“write header”);
}

}

And in the loop function:

//Check For Touchscreen Press
while (true)
{
if (myTouch.dataAvailable())
{
myTouch.read();
x=myTouch.getX();
y=myTouch.getY();

if ((x>=10) && (x<=60)) // Upper row
{
if ((y>=10) && (y<=100)) // Button: Next
{
ButtonAPressed();

}
if ((y>=130) && (y<=229)) // Button: Prev
{
ButtonBPressed();
}
}
if ((x>=160) && (x<=240)) // Upper row
{
if ((y>=10) && (y<=100)) // Button: Log
{
loggerbutton();
}
}
}
}

Is this just not possible or what am I doing wrong?

I'd add some Serial.print() statements to debug where the code actually hangs up. Does the loggerButton() function get called? Does the loggerInit() function get called?

Did logging work before you tried to implement this change?

Logging by itself works fine and the screen display by itself works fine. When I go to the loggerinit branch by way of the logger button function from the void loop function, everything stops. I have tried various iterations of the same thing but every time it starts the loggerinit function, everything locks - I do not even get the button graphics to switch. Can you not run the logging in parallel with other functions?

Can you not run the logging in parallel with other functions?

The Arduino is a simple micro-controller. It can not perform two activities at the same time. So, no you can't run logging in parallel with other functions.

But, that does not appear to be what you are trying to do.

I do not even get the button graphics to switch

That's probably because you are not returning from loggerInit(), and the screen update does not occur until after loggerInit() returns.

First step is to comment out the call to loggerInit() in loggerButton(). Confirm that loggerButton is called, and that it updates the screen correctly.

Then, uncomment the call to loggerInit(), and add some Serial.print() statements to it to figure out where it is dying.

The loggerInit() function really could use a better name. It does not just initialize logging, as it's name implies. It performs the logging, too.

But, before trying to fix that, we need to figure out why loggerInit() isn't returning.

Post all of the loggerInit() function, not just the simplified version in you original post.

I posted the simplified version as I still have to add in all of the variables. the variables aren't killing it is what I am trying to say. I redid the button code so that the screen change happens before loggerInit is called. And actually I plan 2 functions - loggerInit and logger work. The logger work function has all of te variables being logged in it... but again, I do not have that function in this version of the program yet because as with previous versions using push buttons and interrupts and not a touch screen, when the loggerInit function is called, everything stops.

I will add in some serial print lines and see if I can see anything. How do I make it return to the void loop function after the diversion to loggerInit? I tried a simple return line but that did nothing.

Again, Everything dies on execution of loggerInit and it is as was shown... I simplified by not including the loggerWork function because it wasn't done for this version and didn't seem to affect the outcome of it locking up

The old loggerWork function: (The loggerInit function sets up the SD card and this is the actual logging. I split them up per something I saw on another sketch and the idea works perfectly with the screens and I carried the idea over t

void loggerwork()
{
getIMUdata();
getsensordata();

// clear print error
file.writeError = 0;

//Add GPS Info Here********

//Write values to file
file.print(',');
file.print(RwAcc[0]);
file.print(',');
file.print(RwEst[0]);
file.print(',');
file.print(RwAcc[1]);
file.print(',');
file.print(RwEst[1]);
file.print(',');
file.print(RwAcc[2]);
file.print(',');
file.print(RwEst[2]);
file.print(',');
file.print(lean_angle);
file.print(',');
file.print(lean_angle_est);
file.print(',');
file.print(brake_dive);
file.print(',');
file.print(brake_dive_est);
file.print(',');
file.print(analg[5]);
file.print(',');
file.print(analg[6]);
file.print(',');
file.print(analg[7]);
file.print(',');
file.print(analg[8]);
file.print(',');
file.print(analg[9]);
file.print(',');
file.print(analg[10]);
file.print(',');
file.print(analg[11]);
file.print(',');
file.print(analg[12]);
file.print(',');
file.print(analg[13]);
file.print(',');
file.print(analg[14]);
file.print(',');
file.print(analg[15]);
file.println();

if (file.writeError) error("write data");

//don't sync too often - requires 2048 bytes of I/O to SD card
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();

// blink LED to show we are syncing data to the card & updating FAT!
if (!file.sync()) error("sync");
digitalWrite(RPMShiftlightPin, HIGH);
}

because as with previous versions using push buttons and interrupts and not a touch screen, when the loggerInit function is called, everything stops.

So, it really seems that you ought to stop trying to add new functionality until you get this to work.

How do I make it return to the void loop function after the diversion to loggerInit? I tried a simple return line but that did nothing.

You can't. Adding a return to loggerInit(), or reaching the end of the function, will cause a return to the function that called it.

I will add in some serial print lines and see if I can see anything.

Good idea.

Well I seem to have found what's killing it but don't know why it's doing it.

If there is an error when trying to write to the SD card, it stops the program entirely... Why? I am using the basic syntax from the examples

The error coding is:

#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
PgmPrint("error: ");
SerialPrintln_P(str);
if (card.errorCode()) {
PgmPrint("SD error: ");
Serial.print(card.errorCode(), HEX);
Serial.print(',');
Serial.println(card.errorData(), HEX);
}
while(1);
}

when I move the error code to the start of the program, everything dies there...Apparently my one SD card is no longer working and it doesn't like my other one so I have to wait to see if having the SD card in there lets everything work as intended. But I still don't understand why the program breaks when there is an error with the SD card...

if (!card.init(SPI_FULL_SPEED)) error("card.init failed");

// initialize a FAT volume
if (!volume.init(&card)) error("volume.init failed");

// open root directory
if (!root.openRoot(&volume)) error("openRoot failed");

So, look at your error handler. See that statement at the end? The while(1); statement?

That says "Keep doing the body of this statement until 1 is false". The body of the statement is a ; (effectively a no-op). 1 is never false, so, it's an infinite loop that prevents the program from doing anything else.

Probably NOT what you want to do.

That's what I was thinking but didn't fully understand the syntax... Thank you for pointing it out

I removed the while statement but no change in how te program locks up

After each statement in loggerInit(), put a Serial.println() statement. On which statement does it hang? In other words, what is the last statement that successfully executes?

It errors out on volume init and the program stops. I removed the while command but the result is the same. Ideally, the program would notify an error on the lcd that the card is a problem but the screen data should still update and work. Right now, once there is an error with the card, the program stops even with removing the while (1)

I would turn the liggerInit() function inside out.

Which operation in loggerInit() fails, and results in a call to error_P? Do the messages in error_P get printed?

I would do something like this:

int loggerInit()
{
 // initialize the SD card
 if (card.init())
 {
   // initialize a FAT volume
   if (volume.init(card))
   {
     // open root directory
     if (root.openRoot(volume))
     {
       // create a new file
       char name[] = "LOGGER00.CSV";
       for (uint8_t i = 0; i < 100; i++)
      {
         name[6] = i/10 + '0';
         name[7] = i%10 + '0';
         if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;
      }
      if (file.isOpen())
      {
        // write header
        file.writeError = 0;
        file.println("time, lat, long, speed, 
                      date, xA, xE, yA, yE, zA, zE,
                      lean, leane, dive, dive_e,
                      T1mp, RPM, V, TPS, Frt,
                      Rear, AFR, Fork, shock");

        // attempt to write out the header to the file  
        if (file.writeError || !file.sync())
        {
          error("write header");
        }
      }
      else
         error ("file.create");
     }
     else
       error("openRoot");
   }
   else
     error("volume.init");
 }
 else
   error("card.init");
}

Then, I'd probably ditch the error function and just Serial.print() an error message directly.

I changed it to your recommendation and all seems correct now. It is no longer locking up even if there is a card error. I just need to signify on the screen now that there is a card error and it is all good. Thank you for helping me troubleshoot this

Excellent. Thanks for reporting back.