1

I am trying write four digit number to SPIFFS file, and read that four digit from SPIFFS file and display on seven segment.

The code, I am writing as below, I got "0" on each segment, but if manually make number = 4567; then seven segment show proper number on every segment.

Please help me to learn more about how to read & write and convert to object data.

Here is my code;

#include <FS.h>

const char* filename = "/InputInt.txt";
int digit_1 = 0;
int digit_2 = 0;
int digit_3 = 0;
int digit_4 = 0;

int Anode_1 = 16;
int Anode_2 = 14;
int Anode_3 = 5;
int Anode_4 = 4;
int count = 0;
int digits[4] ;
int AnodePins[4] = {4, 5, 14, 16};


int clockPin = 12;
int latchPin = 13;
int dataPin = 15;


int number = 0; //declear the variables

byte numbers[10] {B00000011, B10011111, B00100101, B00001101, B10011001, B01001001, B01000001, B00011111, B00000001, B00001001};


void setup() {
  Serial.begin(115200);
  Serial.println();

  bool success = SPIFFS.begin();

  if (!success) {
    Serial.println("Error mounting the file system");
    return;
  }
  SPIFFS.format();
  File fw = SPIFFS.open(filename, "w");

  if (!fw) {
    Serial.println("Error opening file for writing");
    return;
  }
  char Written = fw.print("1234");

  if (Written == 0) {
    Serial.println("File write failed");
    return;
  }
  fw.close();

  pinMode(Anode_1, OUTPUT);
  pinMode(Anode_2, OUTPUT);
  pinMode(Anode_3, OUTPUT);
  pinMode(Anode_4, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

} //End of setup

void loop() {
  int i;
  File fr = SPIFFS.open(filename, "r");

  if (!fr) {
    Serial.println("Failed to open file for reading");
    return;
  }

  for (i = 0; i < 4; i++) {
    byte number = (Serial.write(fr.read()));
  }
  fr.close();
  break_number(number);
  display_number();
  delay(3000);
} // End of loop

// seperate the input number into 4 single digits
void break_number(int num) {
  Serial.println("");
  digit_1 = num / 1000;
  digits[0] = digit_1;
  Serial.print(" Digit_1: ");
  Serial.println(digit_1);
  int dig_1_remove = num - (digit_1 * 1000);

  digit_2 = dig_1_remove / 100;
  digits[1] = digit_2;
  Serial.print(" Digit_2: ");
  Serial.println(digit_2);
  int dig_2_remove = dig_1_remove - (digit_2 * 100);

  digit_3 = dig_2_remove / 10;
  digits[2] = digit_3;
  Serial.print(" Digit_3: ");
  Serial.println(digit_3);
  digit_4 = dig_2_remove - (digit_3 * 10);

  digits[3] = digit_4;
  Serial.print(" Digit_4: ");
  Serial.println(digit_4);
}

void display_number() {                                             //scanning
  digitalWrite(AnodePins[count], HIGH);                            //turn on the relevent digit
  digitalWrite(latchPin, LOW);                                      //put the shift register to read
  shiftOut(dataPin, clockPin, LSBFIRST, numbers[digits[count]]);    //send the data
  digitalWrite(latchPin, HIGH);                                     //put the shift register to write mode
  delay(0);
  digitalWrite(AnodePins[count], LOW);                            //turn on the relevent digit
  count++;                                                          //count up the digit
  if (count == 4) {                                                 // keep the count between 0-3
    count = 0;
  }
}

Here is the result;

1234
 Digit_1: 0
 Digit_2: 0
 Digit_3: 0
 Digit_4: 0
1234
 Digit_1: 0
 Digit_2: 0
 Digit_3: 0
 Digit_4: 0
1234
 Digit_1: 0
 Digit_2: 0
 Digit_3: 0
 Digit_4: 0

Thanks,

1

I directly see 3 problems with your code:

  1. Serial.write() will not return the written data, but the number of send bytes. This means that in your for loop you are only assigning the written number of bytes to the variable, not the data. But I guess you want to display the actual data, which was read from the file. You should assign the return value of fr.read() to a variable. Then you can send it via Serial.write() and still use that variable for other things later (like displaying).

  2. You need to look into variable scope. You have a global variable number. But in the for loop you are defining a local variable with the same name via

     byte number = ...
    

    This variable is only valid in that specific for loop iteration. When the iteration ends, the variable is thrown away and redeclared in the next iteration. It will not be there anymore, when you leave the for loop. So currently you are saving your data in a variable local to the for loop. It does NOT touch the global variable. Thus the other functions only see the value zero, with which the global variable number was initialized. You can remove the type byte before the variable in the for loop. That makes it an assignment instead of a definition. Thus then you really write the data into the global variable.

  3. Data encoding: Clearly you have your number in the file as ASCII encoded text. But you seem to handle it as binary data. That cannot work. For example: When you read the first character of 1234 (which is written in the file), then you get '1' (the character, not the number). When looking at an ASCII table you can see, that this character corresponds to a decimal number of 49 (or 0x31 in hex). You can convert an ASCII encoded digit to a real number by subtracting the value of the character '0':

     int number = fr.read() - '0';
    

    or

     int number = fr.read() - 48;
    

    (both are equivalent).

    Also you are currently just saving the read character into a single variable. That means, that after the for loop only the last character is left. Since this is a composite number, you should do something to compose it. Like this:

     number = 0;
     int factor = 1000;
     for(int i = 0; i<4; i++){
         number += (fr.read() - '0') * factor;
         factor /= 10;
     }
    

    Note: This is untested, it is not the best way, but the easiest at this point, and it only works for numbers between 1000 and 9999 (4 digit numbers). You can implement this more versatile.

    First we are resetting the number variable, so that old values are not getting in our way. We are using a variable holding the current factor (starting with 1000, since that is the figure in which the first digit lies). Then we go through the 4 characters, reading them. We subtract the character '0' (as described above) and then multiply by the factor. That resulting number is added to the variable number. Then we divide the factor by 10 (getting from 1000 to 100, then to 10 and finally to 1). At the end we can use number like any other integer variable.


Alternative implementation of reading the number, which is suitable for different numbers of digits:

number = 0;
// Prepare character buffer to read the number in
char buffer[10] = ""; // space for maximum 9 digits
int pos = 0; // position variable in the buffer
while(fr.available() && pos < 9){ // loop while there is data left to read in the file or we have no pace left in buffer (leaving one character for the terminating null character
    char c = fr.read(); // read character into variable
    if(isDigit(c)){
        buffer[pos] = c; // save digit in buffer
        pos++; // increment position for the next character
    } else {
       break; // break out of loop, if read character is not a digit (we don't want to read further when a non-digit character comes up)
    }
}
buffer[pos] = 0; // terminate buffer with null character
number = atoi(buffer); // use standard function to convert to integer number

Note:

  • This code is not tested, though it compiles without errors
  • You see, that it is not smaller, than the other one, but can handle different number of digits.
  • You can still use the first version with smaller numbers, if you always pad them with zeros. So instead 991 you would write 0991 to the file. That will make the first version work.
5
  • Thanks Chrisl, I have edit the way you mention, it'sworking well now, you are absolutely right. Mar 17 at 12:36
  • Please let me know, how to keep number as four digit (OCT), number is 1000 and minute 4 should display 0996, but display 9911. Mar 17 at 13:41
  • Sorry, I don't quite understand. Please explain more clearly
    – chrisl
    Mar 17 at 14:40
  • Ok, write number 1008 into file, then read it correct in display, I add some code in loop the final number = number -4; and display number again, start correct from 1008, 1004, 1000, and go to 9911 instead of 0996. Mar 17 at 17:59
  • You almost certainly don't pad the number with zeros to 4 digits, when writing it to the file. As I wrote, that will break the code snippet. I added another way of reading the number, which also supports other digit numbers.
    – chrisl
    Mar 17 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.