I have been working on a program that pseudorandomly generates imperative sentences. The program combines a randomly selected verb, possessive adjective, and noun in order to display a final sentence. I have recently been trying to translate the code from Processing to Arduino, and I ran into some strange behavior today. Here is my code thus far:
#include <SD.h>
int ByteReceived;
int stepToLoad = 1;
int endOfLineNumber = 0;
int stringIndex = 0;
int fileNumber = 0;
File configFile;
char inputString [20];
char inputChar;
String file [3] = {
"verb.txt","adject.txt","noun.txt"};
void setup() {
Serial.begin(9600);
char randSteps[3] = {
random(1,1041),random(1,7),random(1,979)};
pinMode(10, OUTPUT);
SD.begin(10);
for(fileNumber = 0; fileNumber < 3; fileNumber++){
char filename[file[fileNumber].length()+1];
file[fileNumber].toCharArray(filename, sizeof(filename));
if(!SD.exists('\''+filename+'\''))
{
stepToLoad = randSteps[fileNumber];
configFile = SD.open(filename);
getStepData();
Serial.print(inputString);
Serial.print(" ");
endOfLineNumber = 0;
stringIndex = 0;
inputString[0] = '\0';
configFile.close();
}
}
}
void loop() {
if (Serial.available() > 0)
{
ByteReceived = Serial.read();
if(ByteReceived == '1')
{
setup();
}
}
}
void getStepData(){
if (configFile) {
while (configFile.available()) {
inputChar = configFile.read();
if (inputChar != ' '){
inputString[stringIndex] = inputChar;
stringIndex++;
}
else {
endOfLineNumber++;
if (endOfLineNumber == stepToLoad){
inputString[stringIndex] = '\0';
break;
}
else {
stringIndex = 0;
}
}
}
}
}
I am currently implementing a few magic numbers in place of the maximum word count for text files:
char randSteps[3] = {random(1,1041/*Total words in verb.txt*/),random(1,7/*Total words in adject.txt*/),random(1,979/*total words in noun.txt*/)};
This is solely to speed up the boot time while I am debugging the code.
As for the strange behavior, the program will sometimes print a complete phrase like:
"abide my arithmetic"
Other times it prints something like:
"1oomylenddotde his 1oopergesstive"
This behavior can effect just the verb, just the noun, or both. When it effects the verb, it always reads "1oomylenddotde", and when it effects the noun, it reads "1oopergesstive". The possessive adjective is only effected if I force the program to try and read past the total number of words in the text file:
char randSteps[3] = {1,9,1};
at which point the adjective reads "1heir". However, the issue usually arises when the program tries to read past two hundred words on "verb.txt" or "noun.txt":
char randSteps[3] = {200,1,200};
even though I have well over two hundred words in "verb.txt" and "noun.txt". Is this related to SRAM, is it related to the size of endOfLineNumber
, or is it related to some sort of buffer?
After some much needed rest, I have discovered the issue. I was storing my random integers as character values.
char randSteps[3] = {
random(1,1041),random(1,7),random(1,979)};
I have now changed it to:
int randSteps[3] = {
random(1,1041),random(1,7),random(1,979)};
Silly me. Here is the working code:
#include <SD.h>
int ByteReceived;
int stepToLoad = 1;
int endOfLineNumber = 0;
int stringIndex = 0;
int fileNumber = 0;
File configFile;
char inputString [20];
char inputChar;
String file [3] = {
"verb.txt","adject.txt","noun.txt"};
void setup() {
Serial.begin(9600);
pinMode(10, OUTPUT);
SD.begin(10);
int randSteps[3] = {random(1,1041),random(1,7),random(1,979)};
for(fileNumber = 0; fileNumber < 3; fileNumber++){
char filename[file[fileNumber].length()+1];
file[fileNumber].toCharArray(filename, sizeof(filename));
if(!SD.exists('\''+filename+'\''))
{
stepToLoad = randSteps[fileNumber];
configFile = SD.open(filename);
getStepData();
Serial.print(inputString);
Serial.print(" ");
stringIndex = 0;
endOfLineNumber = 0;
inputString[0] = '\0';
configFile.close();
}
}
}
void loop() {
if (Serial.available() > 0)
{
ByteReceived = Serial.read();
if(ByteReceived == '1')
{
setup();
}
}
}
void getStepData(){
if (configFile) {
while (configFile.available()) {
inputChar = configFile.read();
if (inputChar != ' '){
inputString[stringIndex] = inputChar;
stringIndex++;
}
else {
endOfLineNumber++;
if (endOfLineNumber == stepToLoad){
inputString[stringIndex] = '\0';
break;
}
else {
stringIndex = 0;
}
}
}
}
}