Control flow troubles

I'm building a simple EEPROM programmer that allows me to set individual bytes. The idea is to be able to enter an address on the serial monitor, then the data. I managed to cobble a sketch together which does not work properly. The sketch should take any number entered and turn it into a byte, then set 8 digital outputs (pin 2-9) with the individual bits. My only worry is that the sketch does set the first pin (pin 2) but the rest of them. I think the for loop is executed only once. What am I doing wrong?

char inData[10];
int index, i;
boolean started = false;
boolean ended = false;

int AP[8] = {
  2,3,4,5,6,7,8,9};
int AD[8] = {
  0,0,0,0,0,0,0,0};

void setup(){
  Serial.begin(9600);
  Serial.println("ready");
  for (i=0;i<8;i++) {
    pinMode(AP[i],OUTPUT);
  }
  // Setup Data Pins
  for (i=0;i<8;i++) {
    pinMode(AD[i],OUTPUT);
  }
}

void loop()
{
  while(Serial.available() > 0)
  {
    char aChar = Serial.read();
    if(aChar == '>')
    {
      started = true;
      index = 0;
      inData[index] = '\0';
    }
    else if(aChar == '<')
    {
      ended = true;
    }
    else if(started)
    {
      inData[index] = aChar;
      index++;
      inData[index] = '\0';
    }
  }

  if(started && ended){
    int inInt = atoi(inData); // Convert the string to an integer
    for(int j=0; j<8; j++){
      int b = bitRead(inInt,j);
      Serial.println(b);
      if((b&bit(j))>0) {
        AD[j]=HIGH;
      } 
      else {
        AD[j]=LOW;
      }      
      digitalWrite(AP[j],AD[j]);
      delay(100);
    }
    Serial.println(" ");
    // Get ready for the next time
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

What you did is fail to read the documentation for bitRead!!

Replace this section of loop()

  if(started && ended){
    int inInt = atoi(inData); // Convert the string to an integer
    for(int j=0; j<8; j++){
      int b = bitRead(inInt,j);
      Serial.println(b);
      if((b&bit(j))>0) {
        AD[j]=HIGH;
      } 
      else {
        AD[j]=LOW;
      }      
      digitalWrite(AP[j],AD[j]);
      delay(100);
    }

by the succinct:

  if(started && ended){
    int inInt = atoi(inData); // Convert the string to an integer
    for(int j=0; j<8; j++){
      digitalWrite (AP[j], bitRead (inInt,j));  // extract relevant bit and output on relevant pin.
    }

Thank you!

Yes, the bitRead() function returns 1 or 0 (a single bit, already shifted appropriately).

BTW digitalWrite () treats any non-zero value as HIGH, (LOW is the same as 0 is the same as false), so you often don't need
to convert values specifically to HIGH or LOW - just pass directly to digitalWrite.

Thank you, that's a very good point! I'm having trouble with the control flow again. This time a for loop gets executed continuously (as it's supposed to) but cannot make it run only once. Tried the break statement with no success.

char addressBit[10];
char dataBit[6];
int arrayIndex, dataIndex,i;
boolean startedA, endedA, startedD, endedD = false;

int CE  = 47;
int OE  = 48;
int WE  = 49;

int AP[13] = {22,24,26,28,30,32,34,36,38,40,42,44,46};
int DP[8] =  {23,25,27,29,31,33,35,37};

void setup(){
  Serial.begin(9600);
  Serial.println("Enter address in decimal starting with the letter a and finishing it with a period!");
  Serial.println("Then enter data in decimal between d and comma!");
  for (i=2;i<10;i++) {
    pinMode(AP[i],OUTPUT); // address pins
  }
  for (i=9;i<14;i++) {
    pinMode(DP[i],INPUT); // data pins
  }
  // Setup Control Pins
  pinMode(CE, OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(45, OUTPUT);
  
  // Setup Chip
  digitalWrite(CE, HIGH);
  digitalWrite(WE, LOW);
  digitalWrite(OE, HIGH);
}

void loop(){
  digitalWrite(45, HIGH);
  while(Serial.available() > 0)
  {
    char aChar = Serial.read();
    if(aChar == 'r') //beginning of the string
    {
      startedA = true;
      arrayIndex = 0;
      addressBit[arrayIndex] = '\0';
    }
    else if(aChar == '/') ///end of string
    {
      endedA = true;
    }
    else if(startedA)
    {
      addressBit[arrayIndex] = aChar;
      arrayIndex++;
      addressBit[arrayIndex] = '\0';
    }
  }  
if(startedA && endedA){
    int incomingByteA = atoi(addressBit); // Convert the string to an integer
    for(int j=0; j<13; j++){
      digitalWrite (AP[j], bitRead (incomingByteA,j));  // extract relevant bit and output on relevant pin.
      int a = bitRead (incomingByteA,j);
      Serial.println(a);
    }
    Serial.println(" ");
    // Get ready for the next time
    startedA = false;
    endedA = false;
    arrayIndex = 0;
    addressBit[arrayIndex] = '\0';
  }
   delay(1);
    digitalWrite(WE,LOW);      // Write Disabled
    delay(1);
    digitalWrite(CE,HIGH);      // Chip enabled
    delay(1);
    digitalWrite(OE,HIGH);       // Reads Enabled
    delay(1);
  
for(int i=0; i<8; i++){       /// FOR LOOP 
  int DD = digitalRead(DP[i]);
  Serial.println(DD);
  }
 
  delay(100);
}

It's the last bit that gives me headache:

for(int i=0; i<8; i++){       /// FOR LOOP 
  int DD = digitalRead(DP[i]);
  Serial.println(DD);
  }

It seems that this bit prints whatever is coming from the serial as opposed to print the state of the pins. Where did I go wrong? Any suggestions would be appreciated!

I cleaned up the code a bit and still get strange results on the serial monitor.

char addressBit[15];
char dataBit[10];
int arrayIndex, i;
boolean startedA, endedA, flow = false;

int CE  = 47;
int OE  = 48;
int WE  = 49;

int AP[13] = {
  22,24,26,28,30,32,34,36,38,40,42,44,46};
int DP[8] =  {
  23,25,27,29,31,33,35,37};

void setup(){
  Serial.begin(9600);
  Serial.println("Enter address in decimal starting with the letter a and finishing it with a period!");
  Serial.println("Then enter data in decimal between d and comma!");
  for (i=2;i<10;i++) {
    pinMode(AP[i],OUTPUT); // address pins
  }
  for (i=9;i<14;i++) {
    pinMode(DP[i],INPUT); // data pins
  }
  // Setup Control Pins
  pinMode(CE, OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(45, OUTPUT);

  // Setup Chip
  digitalWrite(CE, HIGH);
  digitalWrite(WE, LOW);
  digitalWrite(OE, HIGH);
}

void loop(){
  digitalWrite(45, HIGH);
  while(Serial.available() > 0)
  {
    char aChar = Serial.read();
    if(aChar == 'r') //beginning of the string
    {
      startedA = true;
      arrayIndex = 0;
      addressBit[arrayIndex] = '\0';
    }
    else if(aChar == '/') //end of string
    {
      endedA = true;
    }
    else if(startedA)
    {
      addressBit[arrayIndex] = aChar;
      arrayIndex++;
      addressBit[arrayIndex] = '\0';
    }
  }  
  if(startedA && endedA){ // string filled up
    int incomingByteA = atoi(addressBit); // Convert the string to an integer
    for(int j=0; j<13; j++){
      digitalWrite (AP[j], bitRead (incomingByteA,j));  // extract relevant bit and output on relevant pin.
      int a = bitRead (incomingByteA,j);
      //Serial.println(a);
    }
   
    // Get ready for the next time
    startedA = false;
    endedA = false;
    arrayIndex = 0;
    addressBit[arrayIndex] = '\0';
  }
  
   digitalWrite(WE,LOW);      // Write Disabled
    delay(1);
    digitalWrite(CE,HIGH);      // Chip enabled
    delay(1);
    digitalWrite(OE,HIGH);       // Reads Enabled
    delay(1);

  for(int i=0; i<8; i++){
    int data = digitalRead(DP[i]);
    Serial.print(data);
  }
  Serial.println(" ");
  delay(300);
}

Anyone could verify if it works? Just looking at the serial monitor doesn't help. Still struggle with that last for loop, I wish I knew how to execute it one!

I wish I knew how to execute it one!

bool doItThisTime = true;

void loop()
{
   // some stuff to do every time

   if(doItThisTime)
   {
      // some stuff to do once

      doItThisTime = false;
   }
}

Printing numbers to the serial monitor is an exercise in frustration unless you label them.

  Serial.println("Enter address in decimal starting with the letter a and finishing it with a period!");
    if(aChar == 'r') //beginning of the string

a != r!

I tried what you suggested and now it won't work. What did I do wrong?

char addressBit[15];
char dataBit[10];
int arrayIndex, i;
boolean startedA, endedA = false;
boolean once = true;

int CE  = 47;
int OE  = 48;
int WE  = 49;

int AP[13] = {
  22,24,26,28,30,32,34,36,38,40,42,44,46};
int DP[8] =  {
  23,25,27,29,31,33,35,37};

void setup(){
  Serial.begin(9600);
  Serial.println("Enter address in decimal starting with the letter a and finishing it with a period!");
  Serial.println("Then enter data in decimal between d and comma!");
  for (i=2;i<10;i++) {
    pinMode(AP[i],OUTPUT); // address pins
  }
  for (i=9;i<14;i++) {
    pinMode(DP[i],INPUT); // data pins
  }
  // Setup Control Pins
  pinMode(CE, OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(45, OUTPUT);

  // Setup Chip
  digitalWrite(CE, HIGH);
  digitalWrite(WE, LOW);
  digitalWrite(OE, HIGH);
}

void loop(){
  digitalWrite(45, HIGH);
  while(Serial.available() > 0)
  {
    char aChar = Serial.read();
    if(aChar == 'r') //beginning of the string
    {
      startedA = true;
      arrayIndex = 0;
      addressBit[arrayIndex] = '\0';
    }
    else if(aChar == '/') //end of string
    {
      endedA = true;
    }
    else if(startedA)
    {
      addressBit[arrayIndex] = aChar;
      arrayIndex++;
      addressBit[arrayIndex] = '\0';
    }
  }  
  if(startedA && endedA){ // string filled up
    int incomingByteA = atoi(addressBit); // Convert the string to an integer
    for(int j=0; j<13; j++){
      digitalWrite (AP[j], bitRead (incomingByteA,j));  // extract relevant bit and output on relevant pin.
      int a = bitRead (incomingByteA,j);
      //Serial.println(a);
    }
   
    // Get ready for the next time
    startedA = false;
    endedA = false;
    arrayIndex = 0;
    addressBit[arrayIndex] = '\0';
  }
  
   digitalWrite(WE,LOW);      // Write Disabled
    delay(1);
    digitalWrite(CE,HIGH);      // Chip enabled
    delay(1);
    digitalWrite(OE,HIGH);       // Reads Enabled
    delay(1);
if(once){
  for(int i=0; i<8; i++){
    int data = digitalRead(DP[i]);
    Serial.print(data);
  }
  once = false;
  }
  Serial.println(" ");
  delay(300);
}

Printing numbers to the serial monitor is an exercise in frustration unless you label them.

Code:
Serial.println("Enter address in decimal starting with the letter a and finishing it with a period!");
if(aChar == 'r') //beginning of the string
a != r!

Not sure what you meant by that. Can you explain that please?

What did I do wrong?

It's more what you failed to do. That is, you failed to put each { on a new line. You failed to use Tools + Auto Format to fix the indenting.

Code that bounces
all over the place is
very hard to read. The
Tools + Auto Format
menu item
fixes that problem.

Can you explain that please?

Sure. The message you print says that the text entered should start with an a. The code expects the text to start with an r. An a is not equal to an r.

Oh, cr*p, I copied it from an other sketch. Makes sense. Thanks you!

t's more what you failed to do. That is, you failed to put each { on a new line. You failed to use Tools + Auto Format to fix the indenting.

Code that bounces
all over the place is
very hard to read. The
Tools + Auto Format
menu item
fixes that problem.

I do use Auto Format it's just I can't stand the bracket taking up an extra line. Never thought it can be a problem.

I do use Auto Format

Really? And it did this?

   digitalWrite(WE,LOW);      // Write Disabled
    delay(1);
    digitalWrite(CE,HIGH);      // Chip enabled
    delay(1);
    digitalWrite(OE,HIGH);       // Reads Enabled
    delay(1);
if(once){
  for(int i=0; i<8; i++){
    int data = digitalRead(DP[i]);
    Serial.print(data);
  }
  once = false;
  }

I appreciate your help and am grateful but I feel a but uncomfortable with your schooling.

I appreciate your help and am grateful but I feel a but uncomfortable with your schooling.

OK. I'll knock it off. The only reason I harp on this issue is that I feel that lining up the { and }, and doing consistent indenting, reveals a lot of issues with out-of-order execution and "why isn't his happening here" types of problems.

I suspect that that is why your print statements don't seem to be executed, but because nothing lines up, the only way for me to know that is to copy and paste your code into the IDE, put each { on a new line, and use Tools + Auto Format.

I do appreciate your effort and promise next time I paste my code I'll autoformat it beforehand.

The reason this gets harped on is that mistakes that jump right out of code that is properly indented can hide for days if entropic indentation is used.

It really is worth taking the time: fortune favors those who keep the code properly indented at all times. It doesn't matter if you put the { on a separate line or not (I don't, PaulS does, it's a matter of taste), but I guess that this "underhanging {" style is required for auto-format. I just keep it correct while editing. It's easy enough.

-br

alkopop79:
I do use Auto Format it's just I can't stand the bracket taking up an extra line. Never thought it can be a problem.

Back in the days when programming was done on a 25-line teletype, that was a valid concern. These days with huge desktops everywhere the cost of one extra line in a file is insignificant compared to the advantages of having the { and } pairs lined up vertically so that you can pick out the matching pairs easily so that the actual control structure is obvious. Laying your code out well is one of the most important ways you can make it clear what it does, both for you and for anyone else who has to look at it.

Thank you gents!

This time a different code gives me headache. I'm trying to control two DC motors from the serial. The idea is that the direction and the speed of the two motors is determined by commands starting with the character 'l' (left) or 'r' (right). The character is followed then by a numeric value. A function called 'parse' creates a string and then turns is into an int. However the console tells me otherwise... somehow I got lost.

char inData[10];
int index;
boolean started = false;
boolean ended = false;

void setup()
{
Serial.begin(9600);
Serial.println("READY**");
}

void loop()
{
while(Serial.available() > 0)
{
int l=parse('l');
int r=parse('r');
drive(5,6,'l','L' );
drive(9,10,'r','R');
// Serial.println(Serial.read());
}

}

int parse(char id){
char aChar = Serial.read();
if(aChar == id)
{
started = true;
index = 0;
inData[index] = '\0';
}
else if(aChar == '\n')
{
ended = true;
}
else if(started)
{
inData[index] = aChar;
index++;
inData[index] = '\0';

}

if(started && ended)
{
int inInt = atoi(inData); // Convert the string to an integer
return inInt;
// Get ready for the next time
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
}
void drive(int p1,int p2, int dir, char eyed)
{
if(dir>0){
analogWrite(p1,dir);
analogWrite(p2,0);
Serial.print(eyed);
Serial.print(" ");;
Serial.println('f');
}
else if(dir<0)
{
analogWrite(p1,0);
analogWrite(p2,dir);
Serial.print(eyed);
Serial.print(" ");
Serial.println('b');
}
else if(dir==0)
{
analogWrite(p1,0);
analogWrite(p2,0);
Serial.print(eyed);
Serial.print(" ");
Serial.println('n');
}
}

Where did I go wrong?