Just started Arduino this year!

Just thought i would post somewhere in the forums (Couldn't find anywhere better than here). I recently just bought myself an Complete Microprocessor Pack from Radioshack and have been experimenting with the Arduino uno and LOVE it!

So a little about myself: I'm a college student studying Computer Engineering and Computer Science, i love building things with my hands and programming is by far my biggest interest. I have worked a handfull of different projects (including my own website http://www.mikedmor.com where ill more then likely be blogging a lot more this year about my arduino projects). I love anything to do with android and open source.

Once i get more comfortable with arduino (and circuits i have only taken one class so resistors are still slightly confusing to me) i plan on making my own AR.Drone (You know like the helicopters you can fly with your iphone?) for my android phone.

I was curious if there were any communities that i could become a part of (or if this one is a pretty active one). I would love to see what other people are coming up with and creating with their arduino. But for starters i spent the last two days making this:

Its real simple all it does is take in a string of arguments from the serial and either turns on the red, green, or blue led, or waits a specific amount of time. Or you can start recording your own set of arguments by using the RGB buttons then press play when your done to have it played back to you at the same rate and order you recorded them in.

(BTW i tried to upload a picture but it looks like the upload folder on the server is full. :~)

Welcome. This is the right web place.

BTW, you'r first project, nice, we all start somewhere ("Hello World" :slight_smile: ), but here is a coincidence: check this thread, here is someone trying something very similar (play back a timing sequence), but the program is less than ...ehr ... optimal.

Ha! thanks for the point. I see what you mean though. I have a some programming knowledge to back me up here so i understand slightly where i'm going, but i still could defiantly use feedback and i'm always open to improvement. Here is the code for my version if your interested.

const int RLED=9;
const int GLED=10;
const int BLED=11;
const int bLED=8;
const int PLAY=2;
const int BIND=3;
const int RBUT=4;
const int GBUT=5;
const int BBUT=6;

byte inByte; //initialized instantly in loop
int pause = 0; //wait for wait command
int LEDState=HIGH; // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 80;    // the debounce time; increase if the output flickers
int is_bound=0;
char str[550]="";
int strloc=0;
int rstate=HIGH;
int gstate=HIGH;
int bstate=HIGH;
int aserial=0;
int aserloc=0;

void setup(){
  pinMode(bLED, OUTPUT);
  pinMode(PLAY, INPUT);
  pinMode(BIND, INPUT);
  pinMode(RBUT, INPUT);
  pinMode(GBUT, INPUT);
  pinMode(BBUT, INPUT);
  pinMode(RLED, OUTPUT);
  pinMode(GLED, OUTPUT);
  pinMode(BLED, OUTPUT);
  //setup pins on high (needed for RGB led)
  digitalWrite(RLED, HIGH);
  digitalWrite(GLED, HIGH);
  digitalWrite(BLED, HIGH);
  //Start the serial port
  Serial.begin(9600);
}

void loop(){
  if(Serial.available() > 0 || aserloc != 0){ //check if there is data waiting in the serial
    if(aserloc != 0){
      inByte = str[aserial-aserloc];
      aserloc--;
    }else{
      inByte = Serial.read();
    }
    if(inByte == 'R' || inByte == 'r'){
      if(rstate==HIGH){
        rstate=LOW;
      }else{
        rstate=HIGH;
      }
      Serial.println("Toggling Red.");
    }
    else if(inByte == 'G' || inByte == 'g'){
      if(gstate==HIGH){
        gstate=LOW;
      }else{
        gstate=HIGH;
      }
      Serial.println("Toggling Green.");
    }
    else if(inByte == 'B'|| inByte == 'b'){
      if(bstate==HIGH){
        bstate=LOW;
      }else{
        bstate=HIGH;
      }
      Serial.println("Toggling Blue.");
    }
    else if(inByte == 'O'|| inByte == 'o'){
      rstate = HIGH;
      gstate = HIGH;
      bstate = HIGH;
      Serial.println("Turning off all.");
    }
    else if(inByte == 'W'|| inByte == 'w'){
      pause=0; //Sets pause to 0 for each time you see a W
      if(aserloc != 0){
        inByte = str[aserial-aserloc];
        aserloc--;
      }else{
        inByte = Serial.read();
      }                 
      while(inByte != '!'){ //to end the wait ! needs to be at the end
        if((inByte-'0') < 10) //Note: This was the biggest pain, for some reason the buffer
          //     has many junk values (255 being one). So i have it check
          //     for a value that is below 10 which it should be anyway 
          //     (its only a byte!). also in order to get the correct int
          //     value from a byte you must subtract '0'.
        {
          pause = pause*10; //Muliply last pause by 10 to make it easier
          pause = pause+(inByte-'0'); //Add new inByte as new ones, last is now the tens place.
        }
        if(aserloc != 0){
          inByte = str[aserial-aserloc];
          aserloc--;
        }else{
          inByte = Serial.read();
        }
      }
      Serial.print("Waiting for ");
      Serial.print(pause);
      Serial.println(" miliseconds.");
      delay(pause);
      Serial.println("Done Waiting");
    }
    else{
      Serial.println("Invalid Command... Skipping");
    }
  }
  
  
  digitalWrite(RLED, rstate);
  digitalWrite(GLED, gstate);
  digitalWrite(BLED, bstate);
  
  //This needs to be set to the BIND key!
  int binding = digitalRead(BIND);
  int playing = digitalRead(PLAY);
  int ron     = digitalRead(RBUT);
  int gon     = digitalRead(GBUT);
  int bon     = digitalRead(BBUT);
  
  //Simple button toggles (nothing to see here!)
  if(ron == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
    Serial.println("Manual Red toggle.");
    if(rstate == HIGH){
      rstate = LOW;
    }
    else{
      rstate = HIGH;
    } 
  }
  if(gon == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
    Serial.println("Manual Green toggle.");
    if(gstate == HIGH){
      gstate = LOW;
    }
    else{
      gstate = HIGH;
    } 
  }
  if(bon == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
    Serial.println("Manual Blue toggle.");
    if(bstate == HIGH){
      bstate = LOW;
    }
    else{
      bstate = HIGH;
    } 
  }
  
  //Play button
  if(playing == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
    Serial.println("\nPlaying:");
    Serial.println(str);
    aserial=strlen(str);
    aserloc=strlen(str);
    lastDebounceTime = millis();
    if(aserial==0){
      Serial.println("Nothing to play!");
    }else{
      rstate = HIGH;
      gstate = HIGH;
      bstate = HIGH;
    }
  }

  //Toggle to enter while loop
  if(binding == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
    Serial.println("Start Recording:");
    char str[550]="";
    is_bound = 1;
    lastDebounceTime = millis();
  }
  
  //Changes button state if any of the buttons are presses
  if(binding == HIGH || playing == HIGH || ron == HIGH || gon == HIGH || bon == HIGH){
      lastButtonState = HIGH;
    }
    else{
      lastButtonState = LOW;
    }
    
  strloc=0;
  
  //Loop for remembering keys
  while(is_bound == 1){
    if(Serial.available() > 0){
      Serial.println("Cannot use Serial while binding is on!");
      Serial.println("Exiting binding!");
      is_bound = 0;
    }
    binding = digitalRead(BIND);
    playing = digitalRead(PLAY);
    ron     = digitalRead(RBUT);
    gon     = digitalRead(GBUT);
    bon     = digitalRead(BBUT);
    if(binding == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
      Serial.println("Recording Over!\nSaving...");
      is_bound = 0;
      rstate = HIGH;
      gstate = HIGH;
      bstate = HIGH;
      lastDebounceTime = millis();
      Serial.println("Done Saving!");
    }

    //Red Toggle and wait add
    if(ron == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
      str[strloc] = 'W';
      int wait=millis()-lastDebounceTime;
      char bwait[8]="";
      for(int i=0; wait != 0 && i < 8; i++){
        bwait[i]= (wait%10)+'0';
        wait = wait/10;
      }
      for(int i=(strlen(bwait)-1);i>-1;i--){
        strloc++;
        str[strloc] = bwait[i];
      }
      strloc++;
      str[strloc] = '!';
      strloc++;
      str[strloc] = 'R';
      strloc++;
      if(rstate == HIGH){
        rstate = LOW;
      }
      else{
        rstate = HIGH;
      } 
      Serial.println("Toggle RED");
      lastDebounceTime = millis(); 
    }
    //Green Toggle and wait add
    if(gon == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
      str[strloc] = 'W';
      int wait=millis()-lastDebounceTime;
      char bwait[8]="";
      for(int i=0; wait != 0 && i < 8; i++){
        bwait[i]= (wait%10)+'0';
        wait = wait/10;
      }
      for(int i=(strlen(bwait)-1);i>-1;i--){
        strloc++;
        str[strloc] = bwait[i];
      }
      strloc++;
      str[strloc] = '!';
      strloc++;
      str[strloc] = 'G';
      strloc++;
      if(gstate == HIGH){
        gstate = LOW;
      }
      else{
        gstate = HIGH;
      } 
      Serial.println("Toggle GREEN");
      lastDebounceTime = millis(); 
    }
    //Blue Toggle and wait add
    if(bon == HIGH && lastButtonState == LOW && millis()-lastDebounceTime > debounceDelay){
      str[strloc] = 'W';
      int wait=millis()-lastDebounceTime;
      char bwait[8]="";
      for(int i=0; wait != 0 && i < 8; i++){
        bwait[i]= (wait%10)+'0';
        wait = wait/10;
      }
      for(int i=(strlen(bwait)-1);i>-1;i--){
        strloc++;
        str[strloc] = bwait[i];
      }
      strloc++;
      str[strloc] = '!';
      strloc++;
      str[strloc] = 'B';
      strloc++;
      if(bstate == HIGH){
        bstate = LOW;
      }
      else{
        bstate = HIGH;
      } 
      Serial.println("Toggle BLUE");
      lastDebounceTime = millis(); 
    }

    //Changes button state if any of the buttons are presses
    if(binding == HIGH || playing == HIGH || ron == HIGH || gon == HIGH || bon == HIGH){
      lastButtonState = HIGH;
    }
    else{
      lastButtonState = LOW;
    }
    if(strloc > 500 || millis()-lastDebounceTime > 86400000){
      Serial.println("Ran out of space for remember commands!");
      Serial.println("Exiting loop!");
      is_bound = 0;
      rstate = HIGH;
      gstate = HIGH;
      bstate = HIGH;
    }

    //Changes LED based on if the loop will continue or its state
    digitalWrite(bLED, is_bound);
    digitalWrite(RLED, rstate);
    digitalWrite(GLED, gstate);
    digitalWrite(BLED, bstate);
  }
}

Had to post in a new window due to the character limit. ]:slight_smile: There are a few hickups i have with the code. Mine will also take commands from the serial port, and when your done recording and play it back it will print the a string to the serial that you can copy and run the same thing again from the serial at a later time. But as i said i have one hickup i have not looked into that i can only recreate when i post a recorded command string it sometimes locks up at blue. Oh! and the commands you can use are as follows

R or r = toggle red
G or g = toggle green
B or b = toggle blue
O or o = all off
W#####! = replace # with amount of milliseconds you want you wait for

Let me know what you think! 8)

(Edit: Just wanted to make it clear that i'm using a multicolored LED for the light and one green LED as an indicator that it is recording, then 5 buttons. 3 representing RGB, one for recording toggle, and one for playback)

As you ask what I think, I think that for a "first program" submitted here, it is pretty good. In particular I noticed button debounce logic using timers. A bit lengthy for what it does, but it looked OK. I tried to see your blue-button-hang problem and then noticed a few (fatal?!) flaws, so here are a few(?) suggestions for improvement:

One minor pain with the compiler (and partly because of the chip architecture, to be fair) is that when you write
Serial.println("Hello World") the string is placed into RAM (because all data has to be in RAM to be manipulated on the stack or addresses thereto)

You only have 2K (standard Arduino, and The core also takes a hundered+ bytes RAM) so all those "Toggling Red" messages fill up. You also have an 550 byte array - TWICE. As I do not have time to count the sum of all your strings, but from just glancing through it, I'd say you've exceeded RAM.
The usual explanation for "it works sometimes," or "there is a mystic error when I do x-y-z in the program" is RAM is exceeded. This may explain your "stuck on Blue sometimes".
Correction - I just ran your program and included "memoryFree" to check the memory usage and it says you have 833 bytes left. So it isnt that.

You declare new variables all over in your loop(). The RAM usage is the same, although they reside on the stack, and not on the heap. Also they get set to zero (unless you declare them static), with the notable exception of arrays. The scope is limited to the {} block they are in, but they are allocated at the start of the loop (and a few more details)

Thus you use

    Serial.println("Start Recording:");
    char str[550]="";
    is_bound = 1 ;

Strictly speaking the array could be placed in a new memory location on every run through the loop(), but it just happens to work for you, as you have no other function calls, so the array gets placed in the same spot, and nothing has overwritten it, so it works like static for you. Except the compiler has recognized that you declare it inside a small "{ }" - block and do not use it, and thus it is optimized away - the str[550]="" does nothing. Fortunaty for you, you have a global str[], too. and all errors cancel, so to speak.

I suggest you take all your loop variables and place them outside loop(), as you want them to be static.

      }else{
        inByte = Serial.read();
      }                 
      while(inByte != '!'){ //to end the wait ! needs to be at the end
        if((inByte-'0') < 10) //Note: This was the biggest pain, for some 

reason the buffer
          //     has many junk values (255 being one). So i have it check
          //     for a value that is below 10 which it should be anyway 
          //     (its only a byte!). also in order to get the correct int
          //     value from a byte you must subtract '0'.
        {
          pause = pause*10; //Muliply last pause by 10 to make it easier

The problem is that you do a Serial.read call without having checked Serial.available. What happens is that while you may have sent a line with "W10!" on the serial line, it takes 10ms/char at 9600 baud. You zip through the code (your loop() probably runs in 0.1ms, if it does not execute any delay()) fetch out the W and then start doing Serial.read in a tight while loop. Serial.read returns -1 if no character has arrived yet. Until the "1" has made it, you read it and then get another thousand -1 until the "0" has gotten through.

Your choice of terminator for the number, the '!' is OK, but you could decide that any non-numeric character is the end of the number (ie the next command). Of course that only works if you do the Serial.available correct, and you may want use Serial.peek() to avoid reading the character so it gets read at the top of the loop() for the command processing.

Lastly a note on timing. If you use Arduino v0022 then all Serial.print will hang (just like the delay() function) until the last character is placed on the TX line (where it takes 10ms for the bits to make it out of the UART and up the USB line). As you echo a >10 bytes string on every button push, your button debounce logic is never used; you effectivly wait for 100ms on the first transient change. If you use the V1.0 the characters are stuffed into a buffer (64 bytes for input and 64 for output) and shipped out via interrupt, in which case the Serial.print is less than 1ms. If you attempt to send faster than it is shipped out the old behaviour occurs.

I have NOT examined you recording/playback logic. You say it works, fine. Your button logic uses a global timer and statevariable, thus you can only push one button at a time (design choice or implementation accident?). The timer variables should be unsigned long.

Dont reply on this thread, start a new one under Programming. You can use the PM function to call my attention to such a thread.

Otherwise I hope this lengthy reply has not put you off from asking more. I got carried away, sorry.