Unable to write data to micro sd card

Greetings Friends,

I am working on this project where I am using

-----ARDUINO UNO r3
----16x2 i2c lcd
-----micro sd module
----barcode scanner module
----4x4 matrix keypad
the barcode scanner is used to capture barcode (4 digit barcode). From there we search the barcode number in ''suraj.txt '' file's 1st column (this file has 2 columns ).
i did this with the help of parseInt() function.
if the barcode number already exists , arduino shows corresponding column 2 number.

then program asks if we want to chage the column 2 data or just scan another barcode.

If barcode does not exist in the txt file then program asks if we want to enter a new entry of barcode and corresponding column 2 data.
if yes then program opens the " suraj.txt " at the end and enter the two entries.
After creating entries program again comes to barcode scanning mode.

Everything is working fine expect that whatever entries program make, it does not save them to the micro sd card file "suraj.txt"

while working indivisually with the micro sd card , I can change the indivisual values of the two columns , but after connecting all the devices file writing does not work.

I have tried everything that I can But just can't figure out what the problem is.

i have uploaded the sketch .

ANY HELP WOULD BE MUCH APPRICIATED ....
Thanks

#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

LiquidCrystal_I2C lcd(0x27,16,2);
File myFile;

const byte rx =0;
const byte tx =1;
int amt;

SoftwareSerial scan (rx ,tx);
const byte row =4;
const byte col =4;

char keys[row][col] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'},
};
byte rowPin[row] = {10,9,8,7};
byte colPin[col] = {6,5,3,2};
Keypad kpd(makeKeymap(keys),rowPin,colPin,row,col);


void setup() {
            
            int c;                   
            int i;
            int j; 
            int m;
            int n;
            char button;
            lcd.begin(16,2);
            lcd.backlight();
            lcd.clear();
            scan.begin(9600);
            scan.listen();
        if(!SD.begin(4))
               Serial.println("no SD card");
         else Serial.println("Initialising SD card");
  
           top :
           lcd.clear();
           lcd.setCursor(3,0);
            lcd.print("place card");
                   while (1)  {
            while(scan.available()>0)
         {      c = scan.parseInt(); 
              if(c!=0) {
                
                 goto bottom;
              }
         }
         }

         bottom:      
        myFile = SD.open("suraj.txt",(O_READ|O_WRITE));
       while(myFile.position()<myFile.size()-4)
      {  i = myFile.parseInt();
         m = myFile.position();
         j = myFile.parseInt();
         n = myFile.position();
         if(i==c)
         {
             lcd.clear();
             lcd.print("user exist");
             delay(2000);
             lcd.clear();
             lcd.print("Rs :");
             lcd.setCursor(5,0);
             lcd.print(j);
         delay(3000);
         while(1)
         { button=kpd.getKey();

          if(button=='A')
          { 
             lcd.clear();
            amt = j-DetectNumber();
            myFile.seek(m+1);
            while(myFile.position()<=n)  //This WHILE loop does a 
              myFile.print(" ");       //padding of space

              myFile.seek(m+1);       //position of amount 
              myFile.print(amt);      //write amount to sd file
              myFile.seek(n);
              myFile.flush();       //save the writing to file
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Done");
              delay(500);
              lcd.clear();
              lcd.print("bal :");
              lcd.setCursor(6,0);
              lcd.print(amt);
              delay(2000);
              goto file_close;
          }
           
             if(button=='D')
          {   
             goto file_close;
          }
         }
           
         }
                   
      }
      
             lcd.clear();
            lcd.print("New user!"); 
             while(1)
          {  
            
            button=kpd.getKey();
             if(button=='A')
             { amt =DetectNumber();
               myFile.seek(myFile.size());
               myFile.print("\n");
               myFile.print(c);
               myFile.print(" ");
               myFile.print(amt);
               myFile.print("    ");
               myFile.flush();
             
              lcd.clear();
              lcd.print("Done");
              delay(500);
              lcd.clear();
              lcd.print("New Bal :");
              lcd.setCursor(10,0);
              lcd.print(amt);
              delay(2000);
              goto file_close;
              
             }
             if (button=='D')
             { 
               goto file_close; 
              
             }
   
       }
         
        file_close:
        myFile.flush();
        lcd.clear();
        lcd.print("close file");
        myFile.close();
        delay(3000);
         
          goto top;     
             

  


}

int DetectNumber(void)
{   int temp;
    int num;
    char key;
    lcd.clear();
    while(1){
    top:
    key =kpd.getKey();
    
    if (key=='1')
    {   if(num==0)
          num=1;
          else
          num=(num*10)+1; 
    }
    if (key=='2')
    {   if(num==0)
          num=2;
          else
          num=(num*10)+2;
    }
    if (key=='3')
    {    if(num==0)
          num=3;
          else
          num=(num*10)+3;
      
    }
    if  (key=='4')
    {    if (num==0)
          num= 4;
          else
          num=(num*10)+4;
    }
    if  (key=='5')
    {    if(num==0)
          num=5;
          else
          num=(num*10)+5;
    }
    if  (key=='6')
    {    if(num==0)
         num=6;
         else
         num=(num*10)+6;  
    }
    if   (key=='7')
    {    if(num==0)
         num=7;
         else
         num=(num*10)+7;
    }
    if   (key=='8')
    {    if(num==0)
          num=8;
          else
          num=(num*10)+8;
    }
    if    (key=='9')
    {     if(num==0)
          num=9;
          else
          num=(num*10)+9;
    }
    if    (key=='0')
    {     if (num==0)
          num=0;
          else
          num=(num*10)+0;

    }
    if    (key=='*')
    {    lcd.clear();
         if(num<=9)
          num=0;
          else
          {
          temp=num/10;  
          num=(num-(num-((temp)*10)))/10;
          }
    }
    if    (key=='#')
          { 
            num=0;
            lcd.clear();
            goto top;
                
    }
     if    (key=='A')
            return num;     

    
       lcd.setCursor(0,0);
       lcd.print(num);
         
    }
}


void loop() {

  
} 

As in this Sketch I am trying to search 400 in the file's 1'st column and change its corresponding 2nd column data to 5000.
Here this trick works magically

But when I try the same technique in the main Sketch , it does not work.

please help...

#using-arduino #software #sd #lcd #spi #i2c

#include <SPI.h>
#include <SD.h>

File myFile;


void setup() {
  int i,m,j,n;
  
  Serial.begin(9600);
  if(!SD.begin(4))
              Serial.println("no SD card");
    else Serial.println("Initialising SD card");

      myFile = SD.open("suraj.txt",(O_READ|O_WRITE));
     while(myFile.position()<myFile.size()-4)
     {    i = myFile.parseInt(); 
         m = myFile.position();
         j = myFile.parseInt();
          n = myFile.position();
          if(i==400)
          {myFile.seek(m+1);
           while(myFile.position()<=n)
        {    myFile.print(" ");
            
        } 
            myFile.seek(m+1);
            myFile.print(5000);
          }
          myFile.seek(n);
      Serial.print(i);Serial.print(" "); Serial.println(j);
      
        
     }
           Serial.print(n);
           myFile.close();
       
      
}

void loop() {


}

The "suraj.txt" file only has two columns
it looks something like this.

100 2000
111 3333
444 2222
300 4000

this is a demo file.
So the job here is to scan a barcode using the barcode scanner and search that barcode number in this file.(column 1st)

if the barcode exists then we might want to change its COLUMN 2 value.

AS i described in the previous reply.

I suggest that you add Serial.print/ln statements in strategic places to see what is happening.

This does not help you to solve your problem but here is a significantly more streamlined DetectNumber function; saves you 60 lines of code :slight_smile: And it does not use goto !!

int DetectNumber(void)
{
  int num = 0;
  char key;
  //lcd.clear();

  while (1)
  {
    key = kpd.getKey();

    if (key >= '0' && key <= '9')
    {
      num = num * 10 + (key - '0');
      Serial.println(num);
      // lcd.setCursor(0, 0);
      // lcd.print("    ");
      // lcd.print(num);
    }
    else
    {
      switch (key)
      {
        case '#':
          num = 0;
          Serial.println(num);
          // lcd.setCursor(0, 0);
          // lcd.print("    ");
          break;
        case '*':
          num /= 10;
          Serial.println(num);
          // lcd.setCursor(0, 0);
          // lcd.print("    ");
          // lcd.print(num);
          break;
        case 'A':
          return num;
      }
    }
  }
}

I don't have an LCD so it's replaced by Serial.println().

Hi sterretje

Thank you for the reply.

The program is working fine .But the problem is that whatever It writes to the file ,,doesn't get saved to that .

Is there any problem with myFile.close() function.As it should be placed at certain predefined place ,just out of the loops or braces.

Hey sterretje
You are such a sweetheart.

I was thinking that somebody will definitely point out the right way to handle numbers.

This forum is filled with smart people.

I was thinking

Is using goto multiple time in your program is a bad idea??

goto results in spaghetti code which is not necessary to to use.

I have not looked why your code does not work. Here is a demo that appends at the end of the file.

  1. It uses theSdFat library that you need to install (library manager)
  2. It uses Serial for input and a fixed number for the amount.
  3. It shows some different principles compared to your approach.

Hope this helps a little.

#include <SPI.h>
#include <SdFat.h>
File myFile;

// sd card chip select; modify to need
const int chipSelect = A0;
// SdFat object
SdFat SD;



void setup()
{
  Serial.begin(57600);
  while (!Serial);

  Serial.print("\nInitializing SD card...");

  if (!SD.begin(chipSelect))
  {
    Serial.println("no SD card");
    // hang forever
    for (;;);
  }
  else
  {
    Serial.println("Initialising SD card");
  }
}

void loop()
{
  // number to find; max 9 digits
  char number[10];
  // buffer or file read; max 31 characters plus terminating '\0'
  char buffer[32];
  // flag to indicate of a number was found in the file
  bool found = false;

  // clear number
  memset(number, '\0', sizeof(number));

  // get number to find
  Serial.println("Enter a 3 digit number");
  while (strlen(number) != 3)
  {
    Serial.readBytesUntil('\n', number, sizeof(number) - 1);
  }
  Serial.print("Looking up ");
  Serial.println(number);

  // open file for read
  myFile = SD.open("suraj.txt", O_READ);
  // if success
  if (myFile)
  {
    // debug print
    Serial.println("File opened for reading");
    // read a line at a time from the file
    while (myFile.available() > 0)
    {
      // clear the buffer
      memset(buffer, '\0', sizeof(buffer));
      // read a line from file
      myFile.readBytesUntil('\n', buffer, sizeof(buffer) - 1);
      // debug print
      Serial.println(buffer);
      // split the line
      char *ptr = strchr(buffer, ' ');
      // if <space> found
      if (ptr != NULL)
      {
        // add terminator at correct place
        *ptr = '\0';
        // compare against number
        if (strcmp(buffer, number) == 0)
        {
          // debug print
          Serial.print(buffer);
          Serial.print(", amount = ");
          Serial.println(++ptr);
          // indicate selected number was found
          found = true;
          // and break
          break;
        }
      }
      else
      {
        Serial.println("Corrupt line");
      }
    }
    myFile.close();
  }
  else
  {
    Serial.println("Error opening file for reading");
    return;
  }

  // if number not found
  if (found == false)
  {
    // default amount
    char amount[] = "1000";

    // open file for write at the end
    myFile = SD.open("suraj.txt", O_WRITE | O_APPEND);
    // if success
    if (myFile)
    {
      // debug print
      Serial.println("File opened, appending");
      // append; Serial prints indicate how many bytes were written (or -1 (65535) on error)
      Serial.println(myFile.print("\n"));
      Serial.println(myFile.print(number));
      Serial.println(myFile.print(" "));
      Serial.println(myFile.print(amount));
      myFile.flush();
      myFile.close();
    }
    else
    {
      Serial.println("Error opening file for writing");
      return;
    }
  }
}

I am very grateful to you for your help.

But i am currently unable to check the YOUR SOLUTION ,cause I don't have access to my system..

I will shortly let you know ,If that works for me

Thanks again for the help.

hello sir,

I tried your solution ,it works fine as far as searching and comparing is concerned, but how would we change the entered data (say amount on the line 15)

one approach is using file.position() and file.seek() functions and then padding the perticular line with an array of SPACES.

Then again seek() to particular line and printing variables.
But here something unexpected happens.As I use Array of Spaces to fill the line, sometimes whole file gets corrupted .

At this point I don't know what to do except pulling my HAIR OUT.

I am sure you definitely could tell how to solve that problem as well.

Waiting for Reply...

here is the code

#include<SPI.h>
#include<SD.h>

File myFile;


void setup() { 
                char buff[20];
                char cut[10];
                int posi = 0;
                
              memset(cut,' ',sizeof(cut));        //this is our EARESER
              
                
                
                
                Serial.begin(9600);
               if(  !SD.begin(10))
                {Serial.print("No SD");
                while(1);}
                
                Serial.println("SD initialized");
                myFile = SD.open("suraj.txt",(O_READ|O_WRITE));
         if(myFile)  {  
         
          while(myFile.available())
            {  posi= myFile.position();              // position to later fill line with white space
              myFile.readBytesUntil('\n',buff,17);
            
               
               char *ptr = strchr(buff,' ');
               
              *ptr ='\0';
         
             

              if (strcmp(buff,"140")==0)
              { 
                Serial.println("user exists");
                Serial.print(buff);
                Serial.print("    amount: ");
                Serial.print(++ptr);
                myFile.seek(posi);              //going to the position where match happend
                myFile.print(cut);              //filling the whole line with SPACES (pretending erase)
                myFile.print(buff);             //its same as before cause we only want to change amount value
                myFile.print(" ");
                myFile.print("999");
             
                
              
         
                goto bottom;                  //not using break just skip to "No user exist" line
                
              }
             
            }  
               Serial.println("NO user exist");
   
              bottom:
             
          
              
            myFile.close();  
         }
}

void loop() {
  // put your main code here, to run repeatedly:

}

memset(cut, ' ', sizeof(cut)) does not result in a null-terminated string. The last character needs to be a '\n'.

memset(cut, ' ', sizeof(cut));      //this is our EARESER
cut[sizeof(cut) -1] = '\0';

cut is now a c-string with 9 spaces.

I have tried this thing as well.

It shows some unpredictable behavior .

The problem might be with the fact that the length of the input might change in length

This is what sometimes shows up.

initialization done
101 210    
102 220    
103 230    
104 240    
105 250    
106 268⸮⸮e⸮e⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮B⸮LL⸮̌B⸮LL⸮⸮⸮B⸮LM⸮B⸮LMH⸮LB⸮LM⸮͌B⸮LM⸮⸮⸮B⸮LN⸮B⸮LNH⸮LB⸮L⸮
B⸮L⸮H
LB⸮L⸮⸮
⸮B⸮L⸮⸮
⸮B⸮L⸮

B⸮L⸮H

LB⸮L⸮⸮

⸮B⸮L⸮⸮

⸮B⸮L⸮
B⸮L⸮H
LB⸮L⸮
LB⸮L⸮H
LLB⸮L̈
L⸮B⸮L⸮⸮
L⸮B⸮L⸮
MCF&f⸮⸮⸮⸮F&f⸮⸮⸮⸮F&f⸮⸮⸮⸮F&g⸮⸮F&g$⸮&⸮D00    
141 610    
142 620    
143 630    
144 640    
145 650    
146 660    
147 670    
148 680   

Now I am going mad...
This is crazy..

#include<SPI.h>
#include<SD.h>
#include<SoftwareSerial.h>
#include<Keypad.h>
#include<LiquidCrystal_I2C.h>

SoftwareSerial scanner(0,1);
File myFile;

const byte row =4;
const byte col =4;

char keys[row][col] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'},
};
byte rowPin[row] = {2,3,4,5};
byte colPin[col] = {6,7,8,9};
Keypad kpd(makeKeymap(keys),rowPin,colPin,row,col);
LiquidCrystal_I2C lcd(0x27,16,2);

char buff[20];
char barcode[10];
//int amount;
//char button;
int posi;                //position
int old_bal;           //old balance
                
void setup() { 
                   Serial.begin(9600);
                   Serial.println(F("initialized"));                
                  char cut[10];
                  
              memset(cut,' ',sizeof(cut));       //this is our EARESER
              cut[9]='\0';
             
                  
                
                
                
                                   
                scanner.begin(9600);
                scanner.listen();
                scanner.setTimeout(50);
                lcd.begin(16,2);
                lcd.clear();
                lcd.backlight();
                 if(  !SD.begin(10))
                {lcd.print("No SD");     // Serial.print("No SD");
                while(1);}
                lcd.print("----------------");
                lcd.setCursor(4,0);
                lcd.print("Foodlay");
               delay(2500);
               lcd.clear();
               lcd.setCursor(4,0); 
               lcd.print("made by");
               lcd.setCursor(4,1);
               lcd.print("NEERAJ");
               delay(1000); 
              
                
            
            top:                             //  Serial.println("SD initialized");
              lcd.clear();              // Serial.println("Scanner ready");
              lcd.setCursor(4,0);
              lcd.print("place card");
            
               resetValues();     Serial.println("value reset");
         while(1){ 
                   if(scanner.available()){       
                    scanner.readBytes(barcode,sizeof(barcode)-1);
                 
                                           // Serial.println(barcode);
                   
                    break;
                   }         
                 }
                 Serial.println("scanned barcode");

//WHEN I RUN THIS CODE GIVEN UNDER BOUNDERY, BARCODE READER WORKS WELL BUT WHEN THE 
// WHOLE CODE GETS COMPILED IT JUST HALTS HERE.
//-------------------------------------------------------------

/*
           while(2){
            char push =kpd.getKey();
            if(push=='A')
            { Serial.println("entered A");
              int money =100-detectNumber();
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print(money);
              delay(2000);
              lcd.clear();
              lcd.print("press button"); 
              Serial.println("Going back to while loop");

            }
           }*/
//--------------------------------------------------------------


              
                Serial.println("searching in database");
                myFile = SD.open("suraj.txt",(O_READ|O_WRITE));
         if(myFile)  {  
         
          while(myFile.available())
            {  posi= myFile.position();              // position to later fill line with white space
              myFile.readBytesUntil('\n',buff,17);
           
               
               char *ptr = strchr(buff,' ');
              *ptr ='\0';
              char *ptr_bar = strchr(barcode,' ');
              *ptr_bar = '\0';
              old_bal = atoi(++ptr);
           
              
              if (strcmp(buff,barcode)==0)
              { Serial.println("user exist");
              lcd.clear();                    // Serial.println("user exists");
              lcd.setCursor(0,0);
                                             //  Serial.print(buff);
               lcd.print("Amount: ");
               lcd.setCursor(7,0);
                lcd.print(old_bal);
               Serial.println("printed user information");
               Serial.println("press button"); 
                while(1){
                char button = kpd.getKey();
                   if(button=='A')
                   
                   {Serial.println("Entered A");
                    int amount=old_bal-detectNumber(); 
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("New bal:");
                lcd.setCursor(9,0);
                lcd.print(amount);                
                 Serial.print("New bal:");
                 Serial.println(amount);
                 Serial.println("printing data to file");
                myFile.seek(posi);              //going to the position where match happend
                myFile.print(cut);
                myFile.seek(posi);                               //filling the whole line with SPACES (pretending erase)
                myFile.print(buff);             //its same as before cause we only want to change amount value
                myFile.print(" ");
                myFile.print(amount);
                myFile.flush();
               
                myFile.close();
                delay(2000);
                Serial.println("going scan mode again");
                goto top;
                   }
                   else {
                    Serial.println("you entered key Other then A");
                    myFile.close();
                    Serial.println("going to scan mode");
                    goto top;
                   }   
                }
         
                                  //not using break just skip to "No user exist" line
                
              }
             
            }  
              Serial.println("whole file scanned :No user");
              Serial.println("press A to add other to go scan mode");
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("NO user ");
               while(1){
               
                char button=kpd.getKey();
               if(button=='A')
               {Serial.println("A detected");  
               int amount = detectNumber();
                myFile.seek(myFile.size()+1);
                myFile.print(barcode);
                myFile.print(" ");
                myFile.print(amount);
                myFile.println("    ");
                myFile.flush();
                lcd.clear();
                lcd.print("USER ADDED");
                Serial.println("user added to file");
                delay(500);
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Bal:");
                lcd.setCursor(4,0);
                lcd.print(amount);
                Serial.println("closing the file");
                myFile.close();
                Serial.println("going to scan mode");
                goto top;
               }
               else { 
                Serial.println("Entered Key other than A");
                myFile.close();
                goto top;
               }
               } 
            
         }
}

void loop() {
  // put your main code here, to run repeatedly:

}

void resetValues(void)
{  
   memset(barcode,'\0',sizeof(barcode));
   memset(buff,'\0',sizeof(buff));
   
  
   posi =0;
   old_bal = 0;
 
  
}
int detectNumber(void)

{ Serial.println("detectNumber function called");
  int temp=0;
    int num=0;
    char key;
    lcd.clear();
    while(1){
    top_det:
    key =kpd.getKey();
    
    if (key=='1')
    {   if(num==0)
          num=1;
          else
          num=(num*10)+1; 
    }
    if (key=='2')
    {   if(num==0)
          num=2;
          else
          num=(num*10)+2;
    }
    if (key=='3')
    {    if(num==0)
          num=3;
          else
          num=(num*10)+3;
      
    }
    if  (key=='4')
    {    if (num==0)
          num= 4;
          else
          num=(num*10)+4;
    }
    if  (key=='5')
    {    if(num==0)
          num=5;
          else
          num=(num*10)+5;
    }
    if  (key=='6')
    {    if(num==0)
         num=6;
         else
         num=(num*10)+6;  
    }
    if   (key=='7')
    {    if(num==0)
         num=7;
         else
         num=(num*10)+7;
    }
    if   (key=='8')
    {    if(num==0)
          num=8;
          else
          num=(num*10)+8;
    }
    if    (key=='9')
    {     if(num==0)
          num=9;
          else
          num=(num*10)+9;
    }
    if    (key=='0')
    {     if (num==0)
          num=0;
          else
          num=(num*10)+0;

    }
    if    (key=='*')
    {    lcd.clear();
         if(num<=9)
          num=0;
          else
          {
          temp=num/10;  
          num=(num-(num-((temp)*10)))/10;
          }
    }
    if    (key=='#')
          { 
            num=0;
            lcd.clear();
            goto top_det;
                
    }
     if    (key=='A')
          { Serial.println("returning num");
            return num;     
          }

    
       lcd.setCursor(0,0);
       lcd.print(num);
         
    }
}

while compiling whole code, EXECUTION halts at Barcode Reading stage but then again putting small sample code to check barcode reader ,it 's working.

The sample code is inside the main code in /* */

output when whole code is compiled


initialized
value reset

output when the smaple code is inserted inside the main code


initialized
value reset
scanned barcode
entered A
detectNumber function called
returning num
Going back to while loop
entered A
detectNumber function called
returning num
Going back to while loop

Pins 0 and 1 are the HardwareSerial (on 328P and 2560 based boards, your Uno falls in that category) and are used for communication with the PC. You can't use them for SoftwareSerial while also connecting to the PC and if you don't connect to the PC, you don't have a need for SoftwareSerial as you can just use the usual HardwareSerial.

ok , so you are saying that SoftwareSerial and HardwareSerial both ports can not be used at same time .

but why is it working then for initial part

initialized
value reset

after this the execution halts .