Issue writing to file

12 Apr 2011

I'm trying to write the data coming from a camera over serial to a file. I'm not sure what is breaking what but something isn't working properly and I was hoping a few more eyes could help.

I'm aware that the code below doesn't actually write to a file, it was only put there for me to try and verify where the code is breaking down. So far, it will do everything except get to my while loop. If I comment out the whole file opening and closing my while loop works just fine. I have no idea whats going wrong though, any ideas?

pcSerial.printf("Opening file\r\n");
    FILE *capture = fopen("/local/ucam.bmp", "w");
    pcSerial.printf("Closing fille......");
    fclose(capture); 
    pcSerial.printf("closed\r\n");
    
    while(num_of_pkgs != pkg_counter){
        if(uCamSerial.rxBufferGetCount() == pkg_length){
            for(i = 0; i < pkg_length; i++){
                image_data[i] = uCamSerial.getc();
                pcSerial.printf("%02X", image_data[i]);
            }
            
            pcSerial.printf("\r\n");
            pkg_counter++;
            PACK[5] = (pkg_counter & 0xFF00) >> 8;
            PACK[4] = (pkg_counter & 0xFF);
            
            writeToCam(PACK);           
        }
        else if(uCamSerial.rxBufferGetCount() == extra_bytes && pkg_counter == (total_img_size/pkg_img_size)){//Check to make sure that the buffer contains the expected # of bytes and the pkg_counter is on the last package
            for(i = 0; i < extra_bytes; i++){
                image_data[i] = uCamSerial.getc();
                pcSerial.printf("%02X", image_data[i]);
            }
            
            pcSerial.printf("\r\n");
            pkg_counter++;
            PACK[5] = (pkg_counter & 0xFF00) >> 8;
            PACK[4] = (pkg_counter & 0xFF);
            writeToCam(FACK);//Send ACK signaling image receipt is done           
        }
    }
    
13 Apr 2011

How are num_of_pkgs and pkg_counter initialized? This doesn't appear to have made it into your code snippet here. Is it possible that one of them isn't initialized properly?

13 Apr 2011

num_of_pkgs is global pkg_counter is local to the function that the while loop is in.

I feel like I'm missing some secret sauce here but like I said my while loop works fine when not trying to create a file, I can see the bytes coming over USB Serial.

13 Apr 2011

The only obvious first thought is you are not checking the value of capture as returned by fopen() to make sure the file opening operation was successful or not. I have no idea what is supposed to happen if you call fclose() with a null pointer (should the open fail).

Maybe add:-

    pcSerial.printf("Closing file %p", capture);
    if (capture) fclose(capture);

The %p (print pointer) will either print a valid address of the FILE object or all zeros if null (failed to open file).

It's always worth checking return values for errors before moving on and trying to use them (which may or may not result in a crash depending on the library and how it's implemented).

Once you know for sure you have a useable file handle then it's onto the next problem ;)

14 Apr 2011

Always to my rescue Andy, and thank you for MODSERIAL as well.

I got a pointer address back and just for fun after closing the file I printed a bunch of statements which came through the terminal window but it just won't run my while loop. I even went as far as to even make the loop infinite to make sure it would get hit but nothing.

I'm posting the whole program here in hopes that I was omitting something crucial. Thank you again.

#include "mbed.h"
#include "MODSERIAL.h"
#define EMPTY 0
#define NOTEMPTY 1
#define BAUD 115200

MODSERIAL uCamSerial(p13, p14, 512, 512);
MODSERIAL pcSerial(USBTX, USBRX);
LocalFileSystem local("local");


char RESET[6] = {0xAA, 0x08, 0x00, 0x00, 0x00, 0xFF};
char SYNC[6] = {0xAA, 0x0D, 0x00, 0x00, 0x00, 0x00};
char ACK[6] = {0xAA, 0x0E, 0x0D, 0x00, 0x00, 0x00};
char INIT[6]= {0xAA, 0x01, 0x00, 0x07, 0x07, 0x01};
char SETPKGSIZE[6] = {0xAA, 0x06, 0x08, 0x48, 0x00, 0x00};
char SNPSHOT[6] = {0xAA, 0x05, 0x00, 0x00, 0x00, 0x00};
char GETPIC[6] = {0xAA, 0x04, 0x01, 0x00, 0x00, 0x00};
char PACK[6] = {0xAA, 0x0E, 0x00, 0x00, 0x00, 0x00};
char FACK[6] = {0xAA, 0x0E, 0x00, 0x00, 0xF0, 0xF0};

Ticker tick;

int total_img_size, pkg_length, pkg_img_size, num_of_pkgs, i;
int state = NOTEMPTY;

void changeState(void){
    if(uCamSerial.rxBufferGetCount() == 0){
        state = EMPTY;
    }
}

void writeToCam(char command[]){
    for(int i = 0; i < 6; i++){
        uCamSerial.putc(command[i]);
    }        
}

void responseFromCam(void){
    char bytes_rcvd[6];
    state = NOTEMPTY;
    
    tick.attach_us(&changeState, 50000);
    while(state == NOTEMPTY){
        if(uCamSerial.rxBufferGetCount() >= 6){
            tick.detach();
            for(i = 0; i < 6; i++){
                bytes_rcvd[i] = uCamSerial.getc();
                pcSerial.printf("%02X", bytes_rcvd[i]);//debug statement to find out whats coming back
            }
            pcSerial.printf("\r\n");
            if(bytes_rcvd[0] == 0xAA && bytes_rcvd[1] == 0x0A && bytes_rcvd[2] == 0x01){//If the first three bytes match the DATA response
               total_img_size = ((bytes_rcvd[5] & 0xFF) << 16) + ((bytes_rcvd[4] & 0xFF) << 8) + (bytes_rcvd[3] & 0xFF);//store the last three bytes as the expected size of the image
               pcSerial.printf("Image size is %u bytes\r\n", total_img_size);
            }
            tick.attach_us(&changeState, 50000);    
        }
    }
    tick.detach();
    //delete [] bytes_rcvd;
}

void getImgData(void){   
    
    char image_data[pkg_length];
        
    int pkg_counter = (PACK[5] << 8) + PACK[4];
    pcSerial.printf("The package counter is currently at %u\r\n", pkg_counter);
    int extra_bytes = 0;
    num_of_pkgs = total_img_size/pkg_img_size;
    if((num_of_pkgs%pkg_img_size) != 0){//If there are left over bytes
        num_of_pkgs++;//that means another package is expected
        extra_bytes = (total_img_size%pkg_img_size) + 6;
    }
    pcSerial.printf("The number of incoming packages is %u with a package length of %u\r\n", num_of_pkgs, pkg_length);
   
    FILE *capture = fopen("/local/ucam.bmp", "a");
        
    pcSerial.printf("Closing file %p\r\n", capture);
    if(capture){
     fclose(capture);
    }
    pcSerial.printf("closed\r\n");
        
    while(num_of_pkgs != pkg_counter){
        if(uCamSerial.rxBufferGetCount() == pkg_length){
            
            for(i = 0; i < pkg_length; i++){
                image_data[i] = uCamSerial.getc();
                pcSerial.printf("%02X", image_data[i]);
            }
            
            pcSerial.printf("\r\n");
            pkg_counter++;
            PACK[5] = (pkg_counter & 0xFF00) >> 8;
            PACK[4] = (pkg_counter & 0xFF);
            
            pcSerial.printf("\r\n");
            writeToCam(PACK);           
        }
        else if(uCamSerial.rxBufferGetCount() == extra_bytes && pkg_counter == (total_img_size/pkg_img_size)){//Check to make sure that the buffer contains the expected # of bytes and the pkg_counter is on the last package
            for(i = 0; i < extra_bytes; i++){
                image_data[i] = uCamSerial.getc();
                pcSerial.printf("%02X", image_data[i]);
            }
            
            pcSerial.printf("\r\n");
            pkg_counter++;
            PACK[5] = (pkg_counter & 0xFF00) >> 8;
            PACK[4] = (pkg_counter & 0xFF);
            writeToCam(FACK);//Send ACK signaling image receipt is done           
        }
    }
    
}

int main() {

    pcSerial.baud(BAUD);
    uCamSerial.baud(BAUD);
    
    pkg_length = (SETPKGSIZE[4] << 8) + SETPKGSIZE[3];
    pkg_img_size = pkg_length - 6;//The size in bytes of image data per package 
        
    writeToCam(RESET);
    responseFromCam();
    writeToCam(SYNC);
    responseFromCam();
    writeToCam(ACK);
    writeToCam(INIT);
    responseFromCam();
    writeToCam(SETPKGSIZE);
    responseFromCam();
    writeToCam(SNPSHOT);
    responseFromCam();
    writeToCam(GETPIC);
    responseFromCam();
    writeToCam(PACK);
    getImgData();
    pcSerial.printf("Done");
    
}


15 Apr 2011

Sometimes it's worth doing a "sanity check" and reducing the problem down to it's barest minimum.

Try the following and just check it does what it says on the tin :)

#include "mbed.h"

DigitalOut led1(LED1);

Serial pc(USBTX, USBRX);

LocalFileSystem local("local");

int main() {
    char s[64];
    FILE *capture;

    pc.baud(115200);
        
    capture = fopen("/local/test.txt", "a");
    if (!capture) {
        pc.printf("Error opening file for writing.\n");
    }
    else {
        fprintf(capture, "Hello File World\n");
        fclose(capture);        
    }

    capture = fopen("/local/test.txt", "r");
    if (!capture) {
        pc.printf("Error opening file for reading.\n");
    }
    else {        
        fgets(s, 63, capture);
        fclose(capture);      
        pc.printf(s);  
    }

    // "Graceful" end.
    while(1) {
        led1 = !led1;
        wait(0.2);
    }
}