0

Help with programming
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Help with programming

by cashman04 on Thu Nov 25, 2010 2:33 am

Hello,

Just got my arduino experimenters kit today. Been playing, going through everything. No real problems so far. Except, I don't know anything about programming yet. Here be my question(arr)- I am doing the experiment where I use the shift register to control 8 leds. I have it working no problem, and understand the concept no problem. I just don't get the code. How the hell do I change the pattern, how do I make my own patterns? Here is the sample code I am using.-

Code: Select all | TOGGLE FULL SIZE
/*     ---------------------------------------------------------
 *     |  Arduino Experimentation Kit Example Code             |
 *     |  CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register)   |   
 *     ---------------------------------------------------------
 *
 * We have already controlled 8 LEDs however this does it in a slightly

    * different manner. Rather than using 8 pins we will use just three
    * and an additional chip. * * */

//Pin Definitions //Pin Definitions //The 74HC595 uses a serial communication //link which has three pins int data = 2; int clock = 3; int latch = 4;

//Used for single LED manipulation int ledState = 0; const int ON = HIGH; const int OFF = LOW;

/ * setup() - this function runs once when you turn your Arduino on * We set the three control pins to outputs / void setup() { pinMode(data, OUTPUT); pinMode(clock, OUTPUT);
pinMode(latch, OUTPUT);
}

/ * loop() - this function will start after setup finishes and then repeat * we set which LEDs we want on then call a routine which sends the states to the 74HC595 / void loop() // run over and over again { int delayTime = 100; //the number of milliseconds to delay between LED updates for(int i = 0; i < 256; i++){ updateLEDs(i); delay(delayTime); } }

/ * updateLEDs() - sends the LED states set in ledStates to the 74HC595 * sequence / void updateLEDs(int value){ digitalWrite(latch, LOW); //Pulls the chips latch low shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register digitalWrite(latch, HIGH); //Pulls the latch high displaying the data }

/ * updateLEDsLong() - sends the LED states set in ledStates to the 74HC595 * sequence. Same as updateLEDs except the shifting out is done in software * so you can see what is happening. / void updateLEDsLong(int value){ digitalWrite(latch, LOW); //Pulls the chips latch low for(int i = 0; i < 8; i++){ //Will repeat 8 times (once for each bit) int bit = value & B10000000; //We use a "bitmask" to select only the eighth

                           //bit in our number (the one we are addressing this time through

value = value << 1; //we move our number up one bit value so next time bit 7 will be

                           //bit 8 and we will do our math on it

if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data pin high else{digitalWrite(data, LOW);} //if bit 8 is unset then set the data pin low digitalWrite(clock, HIGH); //the next three lines pulse the clock pin delay(1); digitalWrite(clock, LOW); } digitalWrite(latch, HIGH); //pulls the latch high shifting our data into being displayed }

//These are used in the bitwise math that we use to change individual LEDs //For more details http://en.wikipedia.org/wiki/Bitwise_operation int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};

 int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111,                       B10111111,           B01111111};
 /*
  * changeLED(int led, int state) - changes an individual LED
  * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
  */
  void changeLED(int led, int state){
    ledState = ledState & masks[led];  //clears ledState of the bit we are addressing
    if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to ledState
    updateLEDs(ledState);              //send the new LED state to the shift register
 }


Can anyone clearly explain to me how the pattern works here. I think I see the section of code that is doing it. I just don't understand the math.(i++)? wtf does that mean. I'm not dumb, I just haven't had a real math class in over 8 years(I'm 24), I may have forgotten a few things.

Any help or advice would be appreciated. I think the electronics part of the arduino is no problem for me, it's going to be the programming I'll have trouble with, since I have no experience.

Thanks
cashman04
 
Posts: 25
Joined: Fri Nov 19, 2010 7:04 pm

Re: Help with programming

by stinkbutt on Thu Nov 25, 2010 5:34 am

i++;

is shorthand for:

i = i + 1;
Red M&M, Blue M&M: They all wind up the same color

stinkbutt
 
Posts: 593
Joined: Wed Feb 17, 2010 2:40 am

Re: Help with programming

by adafruit_support_bill on Thu Nov 25, 2010 7:15 am

As stinkbutt says, i++ is equivalent to i = i+1;

The '&' operator as in : int bit = value & B10000000;
is a bitwise AND. This is being used to mask off everything except for the 8th bit of 'value'.

The '<<' operator is the 'shift left' operator. value << 1 will shift all of the bits in 'value' one bit to the left. (The high order bit is discarded).

Here is the code formatted for readability:
Code: Select all | TOGGLE FULL SIZE
/*     ---------------------------------------------------------
 *     |  Arduino Experimentation Kit Example Code             |
 *     |  CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register)   |
 *     ---------------------------------------------------------
 *
 * We have already controlled 8 LEDs however this does it in a slightly
 * different manner. Rather than using 8 pins we will use just three
 * and an additional chip.
 *
 *
 */


//Pin Definitions
//Pin Definitions
//The 74HC595 uses a serial communication
//link which has three pins
int data = 2;
int clock = 3;
int latch = 4;

//Used for single LED manipulation
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;
                       

/*
 * setup() - this function runs once when you turn your Arduino on
 * We set the three control pins to outputs
 */
void setup()
{
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT); 
  pinMode(latch, OUTPUT); 
}

/*
 * loop() - this function will start after setup finishes and then repeat
 * we set which LEDs we want on then call a routine which sends the states to the 74HC595
 */
void loop()                     // run over and over again
{
  int delayTime = 100; //the number of milliseconds to delay between LED updates
  for(int i = 0; i < 256; i++){
   updateLEDs(i);
   delay(delayTime);
  }
}



/*
 * updateLEDs() - sends the LED states set in ledStates to the 74HC595
 * sequence
 */
void updateLEDs(int value){
  digitalWrite(latch, LOW);     //Pulls the chips latch low
  shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
  digitalWrite(latch, HIGH);   //Pulls the latch high displaying the data
}

/*
 * updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
 * sequence. Same as updateLEDs except the shifting out is done in software
 * so you can see what is happening.
 */
void updateLEDsLong(int value){
  digitalWrite(latch, LOW);    //Pulls the chips latch low
  for(int i = 0; i < 8; i++){  //Will repeat 8 times (once for each bit)
  int bit = value & B10000000; //We use a "bitmask" to select only the eighth
                               //bit in our number (the one we are addressing this time through
  value = value << 1;          //we move our number up one bit value so next time bit 7 will be
                               //bit 8 and we will do our math on it
  if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data pin high
  else{digitalWrite(data, LOW);}            //if bit 8 is unset then set the data pin low
  digitalWrite(clock, HIGH);                //the next three lines pulse the clock pin
  delay(1);
  digitalWrite(clock, LOW);
  }
  digitalWrite(latch, HIGH);  //pulls the latch high shifting our data into being displayed
}


//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};
/*
 * changeLED(int led, int state) - changes an individual LED
 * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
 */
 void changeLED(int led, int state){
   ledState = ledState & masks[led];  //clears ledState of the bit we are addressing
   if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to ledState
   updateLEDs(ledState);              //send the new LED state to the shift register
 }

adafruit_support_bill
 
Posts: 76121
Joined: Sat Feb 07, 2009 10:11 am

Re: Help with programming

by mtbf0 on Thu Nov 25, 2010 1:13 pm

cashman04 wrote:I just don't understand the math.(i++)? wtf does that mean.


tain't math, dude. it's c++. have a look at just about any programming book. or take a look at the arduino reference. then try and firgure out the value of i after the following

Code: Select all | TOGGLE FULL SIZE
  i = 0;
  i = i++ + ++i;


i'd tell you myself if i knew for sure.
"i want to lead a dissipate existence, play scratchy records and enjoy my decline" - iggy pop, i need more
User avatar
mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am
Location: oakland ca

Re: Help with programming

by oPossum on Thu Nov 25, 2010 2:24 pm

i will be 3

i = i++ + 1; // Preincrment before addition, i == 1 now
i = 1 + 1; // Postincrement is deferred, i == 1 still
i = 2; // Addition performed, i == 2
i++; // Deferred postincrment is performed, i == 3


i++ is not the same as i = i +1, nor is ++i the same as i = i + 1


i = (i = i + 1) + (i = i + 1);

i will be 4

i = (i = i + 1) + (i = 0 + 1); // i == 1
i = (i = 1 + 1) + i; // i == 2
i = i + i; // The expression (i = i + 1) will return the current value of i, not the value assigned from the earlier addition
i = 2 + 2; // i == 4
I am the Possum, and I approve of this message. Sent from MacBook Wheel Sorry for my bad German.
oPossum
 
Posts: 636
Joined: Fri Oct 26, 2007 12:42 am
Location: Michigan, USA

Re: Help with programming

by stinkbutt on Thu Nov 25, 2010 3:27 pm

OK, finally I can finally make a real post again without trying to read codeblocks on the iPhone (which really doesn't work, btw).

i++ is the equivalent of i = i + 1;
++i is also the equivalent of i = i + 1;

The difference is ++i has a higher priority in order of operations. So:

Code: Select all | TOGGLE FULL SIZE
i = 1;
j = i++;
// i = 2, j = 1

i = 1;
j = ++i;
// i = 2, j = 2


There's also a shorthand to combine incrementing and assignment:

Code: Select all | TOGGLE FULL SIZE
i = 1;
i += 1;
// i = 2 now.

i+= 4;
// i = 6 now.


Now for the bitwise operators:

First realize there's a gazillion different ways to express the same number in c:

Code: Select all | TOGGLE FULL SIZE
i = 16;               // i = 16 here
i = 0xF0;           // i = 16 here as well
i = 0b0001000;  // i = 16 here as well
i = B00010000;  // i = 16 here as well


Now, << and >> are the bitshift operators. So you take your number, convert it to binary, and then shift the 1's and 0's over to the left or right that many spaces. For example:

Code: Select all | TOGGLE FULL SIZE
val = 4;

val << 1;
// val = 8 now.

val >> 2;
// val = 2 now.


The bit shift operators are tantamount to multiplying or dividing by a power of two, so 4 << 2 = 16 because 2^2 = 4, so 4 << 2 = 4 * 4 = 16. But it's more intuitive and clearer to use bit shifting when you're working with binary and/or hexadecimal.

The AND and OR operators are also useful. I'll work in binary because it makes the most sense:

Code: Select all | TOGGLE FULL SIZE
a = 0b00010000;               // 16
b = 0b00010001;               // 17
c = 0b00000001;               // 1

d = a & b;                        // a AND b
// d = 16.  That's the only bit where both a and b are both ON (1).

e = b & c;                         // b AND c
// e = 1.  That the only bit where both b and c are both ON.

f = a & c;                         // a AND c
// f = 0.  There are NO bits where both a and c are both ON.

The same applies for the OR operator:

g = a | b;
// g = 17;

h = a | c;
// h = 17 as well - It get the 16 bit from a, and the 1 bit from c.


There are also assignment shortcuts for AND and OR operators, that work just like the incrementing operators

Code: Select all | TOGGLE FULL SIZE
a = 0b00010000;               // 16
b = 0b00001000;               // 8
c = 0b00001000;               // 8 again

a |= b;
// a = 0b00011000, or 24 now.

a &= c;
// a = 0b00001000, or 8 now.


Two common memes in bitwise programming are turning on one bit with the |= operator, and turning off one bit with the &= operator, like this:

Code: Select all | TOGGLE FULL SIZE
register = 0b00000000;      // 0 - everything off
bit_on = 0b00000001;       // 1 - Last bit on.
bit_off = ^bit_on;             // 254 Everything BUT the last bit on.

// The ^ is a negation operator:  All 0's become 1's and vice versa.

register |= bit_ on;           // Now register = 0b00000001
register &= bit_off;           // Now register's back to 0b00000000;


That should get you started.
Red M&M, Blue M&M: They all wind up the same color

stinkbutt
 
Posts: 593
Joined: Wed Feb 17, 2010 2:40 am

Re: Help with programming

by stinkbutt on Thu Nov 25, 2010 7:07 pm

Oh one more thing: In addition to the incrementing operators, there are DEcrementing operators. So just as all four of these statements are the same thing:

Code: Select all | TOGGLE FULL SIZE
i = i + 1;
i += 1;
i++;
++i;


These four statements are all the same as well:

Code: Select all | TOGGLE FULL SIZE
j = j - 1;
j -= 1;
j--;
--j;


And there are also equivalents for multiplying and dividing:

Code: Select all | TOGGLE FULL SIZE
k = k * 2;
k *= 2;

m = m / 2;
m /= 2;


There's no equivalent for i++ for multiplying and dividing, however. What would be the number you'd use, after all?

Also keep in mind the reasons for all this. Often times you'll have 8 pins on the Arduino which are all digital, so their outputs are either 1 or 0. That means you only need 8 BITS (not BYTES) to describe them. That means one little byte can be used to control all 8 of those pins. So if you want to turn ON one of those pins, you'll need to just change one bit in the entire variable, like this:

Code: Select all | TOGGLE FULL SIZE
int port = 0b00000000;                  // You'll also often see 0x00; Same thing.

port |= ( 1 << 3 );                         // I've just turned on the fourth pin (going RIGHT TO LEFT)
                                                   // If we checked the value of port, it'd be 0b00001000 (or 0x0F or 8)

port |= ( ( 1 << 0 ) | ( 1 << 1 ) )     // I've just turned on the first and second (still right to left) pins.
                                                   // port = 0b00001011

port &= ^( 1 << 0 )                        // I've just turned off the first pin.  Remember the ^ sign that negates the ( 1 << 0 ),
                                                   // so that ^( 1 << 0 ) = 0b11111110
                                                   // port = 0b00001010


Why do we bother? Because there's very little memory on these embedded devices, and any place you can save memory you should. This is a very memory-efficient way to control 8 pins.
Red M&M, Blue M&M: They all wind up the same color

stinkbutt
 
Posts: 593
Joined: Wed Feb 17, 2010 2:40 am

Re: Help with programming

by cashman04 on Fri Nov 26, 2010 7:48 pm

Hokay, well I finally figured it out.

I finally kinda understand now what the i++ was doing there and all that.

I was more looking for a way to just chose individually and manually what led's to turn on. Here's what I ended up with.

Code: Select all | TOGGLE FULL SIZE
int latchPin = 4;
int clockPin = 3;
int dataPin = 2;

void setup() {

  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
 

 
 
{
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 0x00);
    //Or use shiftOout(dataPin,clockPin,MSBFIRST, 11011001);
    digitalWrite(latchPin, HIGH);
    delay(1000);
  }
 
 
 
}


Using that lets me specify the led's to turn on in either binary, or in hexdec form. I think thats how I can do it at least. Seems to be working for me. Anyone see any major problems doing it that way?
cashman04
 
Posts: 25
Joined: Fri Nov 19, 2010 7:04 pm

Re: Help with programming

by cashman04 on Sat Nov 27, 2010 2:15 pm

Ok, I have figured out about 3 different ways to do what I wanted now. NO problems there. Thanks again for clarifying some things for me. But now I have a hopefully much easier question.

So I am trying to set a potentiometers input to set the output number on the display.
Here is the code I have so far-
Code: Select all | TOGGLE FULL SIZE
int value = analogRead(sensePin);
  Serial.println(value);
  if(analogRead(sensePin) == 0){
  digitalWrite(latchPin, LOW);
  dig0();
  digitalWrite(latchPin, HIGH);}
 
  if(analogRead(sensePin) > 100){
  digitalWrite(latchPin, LOW);
  dig1();
  digitalWrite(latchPin, HIGH);}
 
 
  else{
  digitalWrite(latchPin, LOW);
  digb();
  digitalWrite(latchPin, HIGH);}




My question is, how do I write that if the sense pin is between 1 and 100 to digitalWriteblahblahblah

Code: Select all | TOGGLE FULL SIZE
If(analogRead(sensePin) == between 1 and 100){
digitalWrite
blah
blah
blah.


How do I go about writing that?
cashman04
 
Posts: 25
Joined: Fri Nov 19, 2010 7:04 pm

Re: Help with programming

by stinkbutt on Sat Nov 27, 2010 2:21 pm

Easysauce:

Code: Select all | TOGGLE FULL SIZE
    If( (analogRead(sensePin) >= 1) && (analogRead(sensePin) < 100) )
   {
    digitalWrite
    blah
    blah
    blah.
Red M&M, Blue M&M: They all wind up the same color

stinkbutt
 
Posts: 593
Joined: Wed Feb 17, 2010 2:40 am

Re: Help with programming

by cashman04 on Sat Nov 27, 2010 2:30 pm

Wow, thanks so much for that. I found the &&, but had no idea how to use it correctly. didn't know I had to put in the analogRead a second time.

Is this a stupid way to go about doing what I am doing? (I am only doing it, just to learn, So I want to know if I am doing it wrong)

Thanks again though.
cashman04
 
Posts: 25
Joined: Fri Nov 19, 2010 7:04 pm

Re: Help with programming

by stinkbutt on Sat Nov 27, 2010 2:37 pm

No, that's the way most people write their digial logic in Arduino. Inequalities, && (AND), and || (OR.)
Red M&M, Blue M&M: They all wind up the same color

stinkbutt
 
Posts: 593
Joined: Wed Feb 17, 2010 2:40 am

Re: Help with programming

by cashman04 on Sat Nov 27, 2010 2:42 pm

So the best way is to map the different outputs is like I did, with a bunch of else if 's? Cool.
cashman04
 
Posts: 25
Joined: Fri Nov 19, 2010 7:04 pm

Re: Help with programming

by stinkbutt on Sat Nov 27, 2010 4:34 pm

Yeah, you can possibly simplify WITHIN the if/else blocks:

Code: Select all | TOGGLE FULL SIZE
if( val == 0 )
else if( val < 100 )
else


Does much the same thing, just assuming the previous tests.
Red M&M, Blue M&M: They all wind up the same color

stinkbutt
 
Posts: 593
Joined: Wed Feb 17, 2010 2:40 am

Please be positive and constructive with your questions and comments.