help w/ assign binary # digit by digit to an array

hello all,

I am receiving data from serial in the following way:

if (Serial.available() > 0)                        // check to see if there is data
  {
  // read the incoming byte:
  
    for(i=0; i<4; i++)                               //read four bytes in sequence from serial port and  
    {                                                //put them together into one unsinged long variable which is four bytes.
    
      while(Serial.available()==0)                   // Wait until the next byte becomes available
      { 
      }
    
      incomingByte = Serial.read();                  // Get a byte
      Ycomd = Ycomd | (incomingByte << (8*i));       // Compile a variable from the bytes you got
                                        
    }
  
    for(i=0; i<4; i++)
    {
      while(Serial.available()==0)
      {
      }
    
    incomingByte = Serial.read();
    Xcomd = Xcomd | (incomingByte << (8*i));
    
    }

The decimal value of Ycomd and Xcomd that is passed into my code will be in the range of 0 to 1023. I would like to know how to store the binary equivalent of the Ycomd and Xcomd values in separate 10 element arrays with each binary digit in an individual array element. For example if Ycomd == 256, then in binary it is 10000000, so my array for Ycomd would be something like Yarray[] = {0,0,1,0,0,0,0,0,0,0}. I would then like to be able to evaluate each array element to toggle a pin high or low depending on the value in the array. I am not sure how to do this. The code that I have given bellow will probably not work but it will hopefully clarify what I am trying to do. In the following code var is somehow associated with one of the arrays (i'm not sure if this is possible), so that each element in the array is evaluated as the for loop is executed. My idea is that var_, when i == 0 in the for loop, has the value of the first element in the array that it is associated with, when i == 1 in the for loop, var would have the value of the second element in the array, and so on.
*_</em> <em><em>*  for (i = 0; i<10; i++)    {     if var[i] == 1     {      digitalWrite(pin1, HIGH);     }     if var[i] == 0     {      digitalWrite(pin1, LOW);     }*</em></em> <em>_*
any help with this would be greatly appreciated_

If YComd and Xcomd are integers, left shifting the value received 24 bits is going to cause overflow.

It might be simpler to just store the high order byte and low order byte in separate variables, or an array, and then use the bitRead function to read the nth bit whenever you need, than to try to take the bytes apart bit by bit and store each bit separately.

Thank you for your response, but I'm not sure what you mean by

If YComd and Xcomd are integers, left shifting the value received 24 bits is going to cause overflow.

Are you referring to the way that I am creating Ycomd and Xcomd from the serial input? Is there a better way?

I will not have my ATmega168 to test my code with until next week, but are you saying that the following code should do what I explained before?

 bit0 = bitRead(Ycomd,0);            // sets bit0 to the LSB of Ycomd
  bit1 = bitRead(Ycomd,1);
  bit2 = bitRead(Ycomd,2);
  bit3 = bitRead(Ycomd,3);
  bit4 = bitRead(Ycomd,4);
  bit5 = bitRead(Ycomd,5);
  bit6 = bitRead(Ycomd,6);
  bit7 = bitRead(Ycomd,7);
  bit8 = bitRead(Ycomd,8);
  bit9 = bitRead(Ycomd,9);

  int bitarray[] = {bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7, bit8, bit9};                       // array of bits

  for (i = 0; i<10; i++)
    {
     if bitarray[i] == 1
     {
      digitalWrite(pin1, HIGH);
     }
     if bitarray[i] == 0
     {
      digitalWrite(pin1, LOW);
     }  
    }

I read as much as I could find about the bitRead function, but to me it does not seem that I am using it correctly. Also if for example Ycomd == 256 in decimal, will bit8 and bit9 have a value of 0 or will it return an error.

It's very difficult to answer your questions fully, because you're not showing us the whole picture.
We don't know how you've declared "Ycomd", for instance.
An "int" is an integer, but on an Arduino, is only 16 bits wide, which is what PaulS was hinting at.

This:

for (i = 0; i<10; i++)
    {
     if bitarray[i] == 1
     {
      digitalWrite(pin1, HIGH);
     }
     if bitarray[i] == 0
     {
      digitalWrite(pin1, LOW);
     }
    }

will execute so fast you'll only see the result of the last "digitalWrite".

Ycomd is an unsigned long in my code

I'm not sure what the minimum delay could (should) be in my for loop, but I was thinking 100 microseconds should be sufficient. I have not given much thought to this yet, but the chip that I am sending the information to has a serial clock input. Data is clocked into the shift register on the falling edge of the serial clock input, and the data can be transferred at rates up to 50 MHz. Is there a way that I can provide this clock input from the ATmega168?

Any thoughts on how I am using the bitRead function?

bitRead will work with values larger than 8 bits.
It might even be easier to do without the array, e.g.:

for (i = 0; i<10; i++)
{
    digitalWrite(pin1, bitRead(Ycomd, i));
}

Data is clocked into the shift register on the falling edge of the serial clock input

And the clock is where?
Why don't you tell us what you're trying to do, and show us the code?

I am trying to control two Analog Devices AD5293 digital potentiometers http://www.analog.com/static/imported-files/data_sheets/AD5293.pdf

I receive commands for how to adjust the wiper position in the AD5293 chips from matlab, and I store the commands as Ycomd and Xcomd. My code is pretty incomplete right now, but I have posted it bellow to help clarify what I am trying to do. Unfortunately I will not have any hardware until late next week, so I can not test anything right now. Also, for my I/O pins, I just put the numbers 1-16 for now, I have not decided which pins I will actually use yet, so don't read too much into the pin numbers.

// variable declerations
 
  int incomingByte = 0;               // variable for incoming serial data
  unsigned long Ycomd=0, Xcomd=0;     // variables for Y command and X command (values should range from 0 to 1023)
  
  int YRESET = 9;                     // Digital pin, Hardware Reset Pin. Sets the RDAC register to midscale. RESET is activated at the logic high transition. Tie RESET to VLOGIC if not used.
  int YDIN = 10;                      // Digital pin, Serial Data Input. This part has a 16-bit shift register. Data is clocked into the register on the falling edge of the serial clock input.
  int YSLCK = 11;                     // Digital pin, Serial Clock Input. Data is clocked into the shift register on the falling edge of the serial clock input. Data can be transferred at rates up to 50 MHz.
  int YSYNC = 12;                     // Digital pin, Falling Edge Synchronization Signal. This is the frame synchronization signal for the input data. When SYNC goes low, it enables the shift register, and data is transferred in on the falling edges of the following clocks. The selected register is updated on the rising edge of SYNC, following the 16th clock cycle. If SYNC is taken high before the 16th clock cycle, the rising edge of SYNC acts as an interrupt, and the write sequence is ignored by the DAC.
  int YSDO = 13;                      // Digital pin, Serial Data Output. This open-drain output requires an external pull-up resistor. SDO can be used to clock data from the serial register in daisy-chain mode or in readback mode.
  int YRDY = 14;                      // Digital pin, Ready Pin. This active-high, open-drain output identifies the completion of a write or read operation to or from the RDAC register.
  int Ypos = 15;                      // Analog pin, Y position signal from FSM
  int Yerr = 16;                      // Analog pin, Y error signal from FSM

  int XRESET = 1;                     // Digital pin, Hardware Reset Pin. Sets the RDAC register to midscale. RESET is activated at the logic high transition. Tie RESET to VLOGIC if not used.
  int XDIN = 2;                       // Digital pin, Serial Data Input. This part has a 16-bit shift register. Data is clocked into the register on the falling edge of the serial clock input.
  int XSLCK = 3;                      // Digital pin, Serial Clock Input. Data is clocked into the shift register on the falling edge of the serial clock input. Data can be transferred at rates up to 50 MHz.
  int XSYNC = 4;                      // Digital pin, Falling Edge Synchronization Signal. This is the frame synchronization signal for the input data. When SYNC goes low, it enables the shift register, and data is transferred in on the falling edges of the following clocks. The selected register is updated on the rising edge of SYNC, following the 16th clock cycle. If SYNC is taken high before the 16th clock cycle, the rising edge of SYNC acts as an interrupt, and the write sequence is ignored by the DAC.
  int XSDO = 5;                       // Digital pin, Serial Data Output. This open-drain output requires an external pull-up resistor. SDO can be used to clock data from the serial register in daisy-chain mode or in readback mode.
  int XRDY = 6;                       // Digital pin, Ready Pin. This active-high, open-drain output identifies the completion of a write or read operation to or from the RDAC register.
  int Xpos = 7;                       // Analog pin, X position signal from FSM
  int Xerr = 8;                       // Analog pin, X error signal from FSM

  int i = 0, j = 0;                   // variables used for counting
  
  int delay1 = 100;
  int delay2 = 1000;
  
void setup()
{
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
 
// pin declerations
 
  pinMode(YRESET, OUTPUT);             // specifies pins as outputs
  pinMode(YDIN, OUTPUT);
  pinMode(YSLCK, OUTPUT);
  pinMode(YSYNK, OUTPUT);
  pinMode(YSDO, INPUT);                // specifies pins as inputs
  pinMode(YRDY, INPUT);
  pinMode(Ypos, INPUT);
  pinMode(Yerr, INPUT);

  pinMode(XRESET, OUTPUT);
  pinMode(XDIN, OUTPUT);
  pinMode(XSLCK, OUTPUT);
  pinMode(XSYNK, OUTPUT);
  pinMode(XSDO, INPUT);
  pinMode(XRDY, INPUT);
  pinMode(Xpos, INPUT);
  pinMode(Xerr, INPUT);

}

void loop() 
{
  
  if (Serial.available() > 0)                        // check to see if there is data in the bus
  {
  // read the incoming byte:
    Serial.print("DEBUG: loop1\r\n");
  
    for(i=0; i<4; i++)                               //read four bytes in sequence from serial port and  
    {                                                //put them together into one unsinged long variable which is four bytes.
    
      while(Serial.available()==0)                   // Wait until the next byte becomes available
      { 
      }
    
      incomingByte = Serial.read();                  // Get a byte
      Ycomd = Ycomd | (incomingByte << (8*i));       // Compile a variable from the bytes you got
                                        
                                        
    }
  
    for(i=0; i<4; i++)
    {
      while(Serial.available()==0)
      {
      }
    
    incomingByte = Serial.read();
    Xcomd = Xcomd | (incomingByte << (8*i));
    
    }
 
// say what you got (for testing):
  Serial.print("I received: ");
  Serial.print(", ");
  Serial.print(Ycomd, DEC); 
  Serial.print(", ");
  Serial.println(Xcomd, DEC);
  Serial.print(", ");
  
  int bit0 = bitRead(Ycomd,0);            // sets bit0 to the LSB of Ycomd
  int bit1 = bitRead(Ycomd,1);
  int bit2 = bitRead(Ycomd,2);
  int bit3 = bitRead(Ycomd,3);
  int bit4 = bitRead(Ycomd,4);
  int bit5 = bitRead(Ycomd,5);
  int bit6 = bitRead(Ycomd,6);
  int bit7 = bitRead(Ycomd,7);
  int bit8 = bitRead(Ycomd,8);
  int bit9 = bitRead(Ycomd,9);
  
  int bitarray[] = {bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7, bit8, bit9};                       // array of bits
  
/// Y Command Sequence
   
  digitalWrite(YSYNK ,LOW);           // The write sequence begins by bringing the SYNC line low 
  delayMicroseconds(delay2);          // not sure how long this delay should be
  
/// Command 4 in table 10 in AD5293 manual, enables update of wiper position
 
  for(i=0; i<3; i++)
    {
      digitalWrite(YDIN, LOW);
      delayMicroseconds(delay1);      // not sure how long this delay should be
    }
  
  for(i=0; i<2; i++)
    {
      digitalWrite(YDIN, HIGH);
      delayMicroseconds(delay1);
    }
  
  for(i=0; i<9; i++)
    {
      digitalWrite(YDIN, LOW);
      delayMicroseconds(delay1);
    }
  
  digitalWrite(YDIN, HIGH);
  delayMicroseconds(delay1);
  digitalWrite(YDIN, LOW);
  delayMicroseconds(delay1);
  
/////////////////////////////////////////////////////////////////////// 
  
  digitalWrite(YSYNK, HIGH);          // When SYNC returns high, the serial data-word is decoded
  delayMicroseconds(delay2);
  digitalWrite(YSYNK ,LOW);
  delayMicroseconds(delay2);
  
/// Command 1 in table 10 in AD5293 manual, writes contents of serial register data to RDAC
  
  for(i=0; i<5; i++)
    {
      digitalWrite(YDIN, LOW);
      delayMicroseconds(delay1);
    }
  
  digitalWrite(YDIN, HIGH);
  delayMicroseconds(delay1);

  for (i = 9; i>-1; i--)
    {
     
      if bitarray[i] == 1
     {
      digitalWrite(YDIN, HIGH);
        delayMicroseconds(delay1);
     }
     
     if bitarray[i] == 0
     {
      digitalWrite(YDIN, LOW);
        delayMicroseconds(delay1);
     }  
    
   }
    
///////////////////////////////////////////////////////////////////////
  
  digitalWrite(YSYNK, HIGH);
  delayMicroseconds(delay2);
  digitalWrite(YSYNK ,LOW);
  delayMicroseconds(delay2);
  
/// command 2 in table 10 in AD5293 manual, Read RDAC wiper setting from SDO output in the next frame

  for (i=0; i< 4; i++)
    {
      digitalWrite(YDIN, LOW);
      delayMicroseconds(delay1);
    }
  
  digitalWrite(YDIN, HIGH);
  delayMicroseconds(delay1);
  
  for (i=0; i<11; i++)
    {
      digitalWrite(YDIN, LOW);
      delayMicroseconds(delay1);
    }

///////////////////////////////////////////////////////////////////////
  
  digitalWrite(YSYNK, HIGH);
  delayMicroseconds(delay2);
  digitalWrite(YSYNK ,LOW);
  delayMicroseconds(delay2);
  
/// command 0 in table 10 in AD5293 manual, NOP command. Do nothing
  
 for (i=0; i< 16; i++)
    {
      digitalWrite(YDIN, LOW);
      delayMicroseconds(delay1);
    } 
  
///////////////////////////////////////////////////////////////////////

  digitalWrite(YSYNK, HIGH);
  delayMicroseconds(delay2);
  
  Serial.flush(); //Flush serial input buffer before the next cycle 
  
  }

}

As far as the clock goes. I really don't know what I am doing. I was hoping that there is a way to provide the clock input to the AD5293 chips from the ATmega168. I have not been able to get into this at all yet.

Have you thought about using shiftOut, or at least looking at the source for ideas?
http://arduino.cc/en/Reference/ShiftOut

What range of values are you expecting to store in Ycomd and Xcomd? An unsigned long (32 bits) can hold values in the range 0 to 4,294,967,295. Will you really be receiving numbers that large?

The datasheet says that the potentiometers have 1024 discrete settings. 1024 will fit into a signed or unsigned int (16 bits) with lots of elbow room.

I was unaware of the shiftOut function. It looks to me that shiftOut should simplify my code and answer my question about the clock and delays. If I understand correctly I should be able to do the following:

unsigned int Ycomd = 0;
int incomingByte = 0;
int i = 0;
int YDIN = 10;
int clockPin = 17;

void setup()
{
  Serial.begin(9600);
 
  pinMode(YDIN, OUTPUT);
  pinMode(YSYNK, OUTPUT);
  pinMode(clockPin, OUTPUT);
  
}
  
void loop() 
{
  
   if (Serial.available() > 0)
  {
    Serial.print("DEBUG: loop1\r\n");
  
    for(i=0; i<4; i++) 
    {
    
      while(Serial.available()==0)
      { 
      }
    
      incomingByte = Serial.read();
      Ycomd = Ycomd | (incomingByte << (8*i));
                                                                           
    }
 
 Ycomd = Ycomd + 1024;
 
  digitalWrite(YSYNK ,LOW);
  delayMicroseconds(100);
 
  shiftOut(YDIN, clockPin, MSBFIRST, (Ycomd >> 8));
  shiftOut(YDIN, clockPin, MSBFIRST, Ycomd);
 
  delayMicroseconds(100);
  digitalWrite(YSYNK, HIGH);
  delayMicroseconds(100);
 
  }
}

The reason I added the line:

Ycomd = Ycomd + 1024;

is because the command that is sent to the digital potentiometer has the following form 000001D9D8D7D6D5D4D3D2D1D0, where D9, D8, and so on are bits representing a decimal value between 0 and 1023. I believe that according to the way that I have written the code above, that if a 256 was received from serial, then Ycomd == 256, so the first shiftOut would send a 00000101 and the second shift out would send a 00000000. Does this seem to be the correct usage of shiftOut? Also, I would need to connect the clockPin to the clock input on the AD5293 for this to work, right?

As far as the unsigned long Ycomd that I wrote before. I knew that it was overkill, but should it cause a problem or is it just unnecessary or bad programing?