Saturday, September 15, 2012

Atmega 328p Exit ign!!

This is a project I have been working on for quite some time now (about 2 years to be exact). And I have FINALLY.... Well... ALMOST have it completed, however I am finally ready to post the source and schematic for it (beta still btw). Hope you like!

Also there will be a youtube post with it in action soon.


Exit sign poining to the bloggest with the bestest erm... best something :P




Another pic of the exit sign in action

Reflective material behind exit sign with leds (i.e. yep you guessed it, aluminum foil)

Full underface of exitsign

The back

I wanted the batteries to be housed inside it but wanted easy access to them without disturbing the inner parts. Also of note, on the left we have the Microphone jack (because the whole original purpose was for it to light to music which it does :) and on the right we have the mode selection non-functioning switch (do NOT buy these crap radio shack buttons! I found out the hard way :/)

Ah yes, the inner rats nest and pcbs that are the brains of the operation.

This is pretty much just your standard arduino-esque board with an Atmega328p, and a really rough looking ICSP port minus the VCC pin.

Here is where the magic happens ;) This is (though you cant see it from the cap on top) is an lm368 audio amplifier/generic opamp I got at radioshack that converts the analog audio from the microphone jack to power waves to be read by the analog 01 port from the atmega to then convert to digital to process and display the sound on the board.

Back where the mic jack and that crappy switch is.

Sensitivity pot for the amplifier. Works like a charm too.

Here's pretty much the closest thing to a good schematic I have atm:

I used the Arduino IDE to compile this code, and just pushed it via avrdude through icsp, so just to give a heads up I don't think this will work in avrstudio (well without a few adjustments anyways).

 Source Code:
****BE WARNED! THIS IS BETA STILL! I CAN'T GUARANTEE IT IS STABLE AND THAT IT ALL WORKS!!!****

/* 
Honkey Hacker presents
The Audio Light Organ Exit Sign
selectable modes of operation
Utilizing PWM and analog output techniques
Free as in libre nachos!
*/ 

//Global variables and reassignment of pins
// < E X I T >
int l = 6;// define pin 6 as exit sign <
int e = 3;// define pin 3 as exit sign E
int x = 5;// define pin 5 as exit sign X
int i = 11;// define pin 11 as exit sign I
int t = 10;// define pin 10 as exit sign T
int r = 9;// define pin 9 as exit sign >
int buttnPin = 2;
int buttonVal =0;
int modeSwitch = 1;
int buttonPress = 1;
const int analogPin = 0;  

//Define Modes of operation
void Startup();
void StandardMode();
void MusicMode1();
void MusicMode2();
void MusicMode3();

//Define Effects
void ClearAll();
void Light(int light, int power);
void LightAll(); //1
void DimAll();//2
void ChaseRight();//4
void ChaseLeft();//5
void Mosaic();//6
void SoftChaseRight();//7
void SoftChaseLeft();//8
void Flicker();//9
void MultiFlicker();//10
void SimpleFlicker();//11
void InsideOut();//12
void OutsideIn();//13

void setup() {
 pinMode(2, INPUT);
}

void loop() {
Startup();
}

void Startup(){
InsideOut();OutsideIn();ClearAll(); Mosaic(); Mosaic();StandardMode();
}

void StandardMode(){

  do{
  buttonVal = digitalRead(buttnPin);

    if(buttonVal == LOW)  {buttonPress++;}
    if(buttonPress > 1){modeSwitch++; buttonPress = 0;}
    switch (modeSwitch) {
      case 1: //music mode 1
              delay(100);
              MusicMode1();
        break;
      case 2: //music mode 2
              delay(100);
              MusicMode2();
        break;
      case 3: //music mode 3
              delay(100);
              MusicMode3();
        break;
      case 4: //mosaic
              Mosaic();
        break;
      case 5: //Chase right
              ChaseRight();
        break;
      case 6: //Chase left
              ChaseLeft(); 
        break;
      case 7: //Chase right then left
              ChaseRight(); ChaseLeft(); 
        break;
      case 8: //soft chase right
              SoftChaseRight(); 
        break;
      case 9: //soft chase left
              SoftChaseLeft(); 
        break;
      case 10: //soft chase right then left
              SoftChaseRight(); 
              SoftChaseLeft(); 
        break;
      case 11: //flicker
              Flicker();
        break;
      case 12: //multiflicker
              MultiFlicker();
        break;
      case 13: //simpleflicker
              SimpleFlicker(); 
        break;
      case 14: //inside out
              InsideOut();
        break;
      case 15: //outside in
              OutsideIn();
        break;
      case 16: //inside out then back in
              InsideOut();
              OutsideIn();
        break;
      case 17: //test light <
              ClearAll();
              Light(l, 255);
        break;
      case 18: //test light E
              ClearAll();
              Light(e, 255);
        break;
      case 19: //test light X
              ClearAll();
              Light(x, 255);
        break;
      case 20: //test light I
              ClearAll();
              Light(i, 255);
        break;
      case 21: //test light T
              ClearAll();
              Light(t, 255);
        break;
      case 22: //test light >
              ClearAll();
              Light(r, 255);
        break;
      case 24: //Lightall then DimAll
              LightAll(); delay(1000);DimAll();delay(1000);
        break;
      case 25: //demo mode
              Light(x,255);delay(200);InsideOut();OutsideIn();SimpleFlicker(); ClearAll(); Mosaic(); Mosaic(); MultiFlicker(); ChaseRight(); ChaseLeft(); Flicker(); SoftChaseRight(); SoftChaseLeft(); LightAll(); delay(1000);DimAll();    
        break;
      case 26: //reset button mode value
              modeSwitch = 1;
        break;
      default: //Error code 3
              ClearAll();
              Light(e,255);
     }
  }while(1);
}

void Light(int light, int power)
{
  ClearAll();
  analogWrite(light, power);
}

void MusicMode1(){ //this will be used to test input with serial out. please discard the slow ass serial out once finished :)
  int mn = 1024;     // mn only decreases
  int mx = 0;        // mx only increases
  // Perform 10000 reads. Update mn and mx for each one.
  for (int i = 0; i < 10; ++i) {
    int val = analogRead(analogPin);
    mn = min(mn, val);
    mx = max(mx, val);
  }

  // Send min, max and delta over Serial
/*  Serial.print("m=");
  Serial.print(mn);  
  Serial.print(" M=");
  Serial.print(mx);  
  Serial.print(" D=");
  Serial.print(mx-mn);  
  Serial.println();  */
  if (mx-mn <= 250){analogWrite(l,0);analogWrite(e,0); analogWrite(x,0);analogWrite(i,0);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 251 && mx-mn <= 400){analogWrite(l,255);analogWrite(e,0); analogWrite(x,0);analogWrite(i,0);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 401 && mx-mn <= 500){analogWrite(l,255);analogWrite(e,255); analogWrite(x,0);analogWrite(i,0);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 551 && mx-mn <=650){analogWrite(l,255);analogWrite(e,255); analogWrite(x,255);analogWrite(i,0);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 651 && mx-mn <=850){analogWrite(l,255);analogWrite(e,255); analogWrite(x,255);analogWrite(i,255);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 851 && mx-mn <=900 ){analogWrite(l,255);analogWrite(e,255); analogWrite(x,255);analogWrite(i,255);analogWrite(t,255);analogWrite(r,0);}
  if (mx-mn >= 701){analogWrite(l,255);analogWrite(e,255); analogWrite(x,255);analogWrite(i,255);analogWrite(t,255);analogWrite(r,255);}
}

void MusicMode2(){ //here for filler until finished testing.

  int mn = 1024;     // mn only decreases
  int mx = 0;        // mx only increases
  int val = 0;
  // Perform 10000 reads. Update mn and mx for each one.
  for (int i = 0; i < 500; ++i) {
    val = analogRead(analogPin);
    mn = min(mn, val);
    mx = max(mx, val);
  }

  // Send min, max and delta over Serial
  analogWrite(l,mx-mn);analogWrite(e,mx-mn); analogWrite(x,mx-mn);analogWrite(i,mx-mn);analogWrite(t,mx-mn);analogWrite(r,mx-mn);
}


void MusicMode3(){//here for filler until finished testing.

  int mn = 1024;     // mn only decreases
  int mx = 0;        // mx only increases

  // Perform 10000 reads. Update mn and mx for each one.
  for (int i = 0; i < 500; ++i) {
    int val = analogRead(analogPin);
    mn = min(mn, val);
    mx = max(mx, val);
  }

  if (mx-mn <= 200){analogWrite(l,0);analogWrite(e,0); analogWrite(x,0);analogWrite(i,0);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 201 && mx-mn <= 350){analogWrite(l,0);analogWrite(e,0); analogWrite(x,255);analogWrite(i,255);analogWrite(t,0);analogWrite(r,0);}
  if (mx-mn >= 351 && mx-mn <= 550){analogWrite(l,0);analogWrite(e,255); analogWrite(x,255);analogWrite(i,255);analogWrite(t,255);analogWrite(r,0);}
  if (mx-mn > 551){analogWrite(l,255);analogWrite(e,255); analogWrite(x,255);analogWrite(i,255);analogWrite(t,255);analogWrite(r,255);}
}

void ClearAll(){
  analogWrite (l,0);
  analogWrite (e,0);
  analogWrite (x,0);
  analogWrite (i,0);
  analogWrite (t,0);
  analogWrite (r,0);
}

void Mosaic()
{
  ClearAll();
  int breaker = 0;
  int timeLight = 0;  
  int timeLight1 = 0;
  int timeLight2 = 255;
  do{
       if(timeLight < 255){
        analogWrite(l, timeLight1);
        analogWrite(x, timeLight1);
        analogWrite(t, timeLight1++);
        analogWrite(e, timeLight2);
        analogWrite(i, timeLight2);
        analogWrite(r, timeLight2--);
      }
  buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     if (timeLight > 255){
        analogWrite(l, timeLight1);
        analogWrite(x, timeLight1);
        analogWrite(t, timeLight1--);
        analogWrite(e, timeLight2);
        analogWrite(i, timeLight2);
        analogWrite(r, timeLight2++);
      }
    timeLight++;
    delay(5);
    if (timeLight > 510){breaker=1;}
  }
  while(breaker < 1);
}

void ChaseRight(){
  ClearAll();
  analogWrite(l,255); delay(500);
  analogWrite(l,0);
buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(e,255); delay(500);
  analogWrite(e,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(x,255); delay(500);
  analogWrite(x,0);
 buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(i,255); delay(500);
  analogWrite(i,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(t,255); delay(500);
  analogWrite(t,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(r,255); delay(500);
  analogWrite(r,0);

}

void ChaseLeft(){
  ClearAll();
  analogWrite(r,255); delay(500);
  analogWrite(r,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(t,255); delay(500);
  analogWrite(t,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(i,255); delay(500);
  analogWrite(i,0);
 buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(x,255); delay(500);
  analogWrite(x,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(e,255); delay(500);
  analogWrite(e,0);
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  analogWrite(l,255); delay(500);
  analogWrite(l,0);
}

void SoftChaseRight(){
  ClearAll();
  for(int bright=0; bright < 255; bright++)
  {
   analogWrite(l, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(e, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(x, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(i, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(t, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(r, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
    for(int bright=255; bright > 0; bright--)
  {
   analogWrite(l, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(e, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(x, bright); delay(2);
  }
   buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(i, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(t, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(r, bright); delay(2);
  }
  
}
void SoftChaseLeft(){
  ClearAll();
  for(int bright=0; bright < 255; bright++)
  {
   analogWrite(r, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(t, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(i, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(x, bright); delay(2);
  }
   buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(e, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(l, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
    for(int bright=255; bright > 0; bright--)
  {
   analogWrite(r, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(t, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(i, bright); delay(2);
  }
  
   buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(x, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(e, bright); delay(2);
  }
  buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(l, bright); delay(2);
  }  
}

void LightAll(){
  ClearAll();
  for(int bright=0; bright < 255; bright++)
  {
    analogWrite(l, bright);
    analogWrite(e, bright);
    analogWrite(x, bright);
    analogWrite(i, bright);
    analogWrite(t, bright);
    analogWrite(r, bright); delay(2);
    buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  }  
}
void DimAll(){
  ClearAll();
  for(int bright=255; bright > 0; bright--)
  {
    analogWrite(l, bright);
    analogWrite(e, bright);
    analogWrite(x, bright);
    analogWrite(i, bright);
    analogWrite(t, bright);
    analogWrite(r, bright); delay(2);
    buttonVal = digitalRead(buttnPin);
if(buttonVal == LOW)  {buttonPress++;}
  }
}  
void Flicker()
{
  int timego;
  do{
    timego++;
    int light = random(256);
    analogWrite(l,light);
    analogWrite(e,light);
    analogWrite(x,light);
    analogWrite(i,light);
    analogWrite(t,light);
    analogWrite(r,light);
     buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  }while(timego < 10000);
}

void MultiFlicker()
{
  int timego;
  do{
    timego++;
    int light1 = random(100, 256);
    int light2 = random(80);
    int light3 = random(256);
    analogWrite(l,light1);
    analogWrite(e,light1);
    analogWrite(x,light2);
    analogWrite(i,light2);
    analogWrite(t,light3);
    analogWrite(r,light3);
     buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  }while(timego < 10000);
}

void SimpleFlicker()
{
  int timego;
  do{
    timego++;
    int light = random(256);
    analogWrite(l,255);
    analogWrite(e,light);
    analogWrite(x,255);
    analogWrite(i,light);
    analogWrite(t,255);
    analogWrite(r,255);
     buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
  }while(timego < 10000);
}

void InsideOut()
{
  ClearAll();
  for(int light=0;light < 255; light++)
  {
     analogWrite(x,light);
     analogWrite(i,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=0;light < 255; light++)
  {
     analogWrite(e,light);
     analogWrite(t,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=0;light < 255; light++)
  {
     analogWrite(r,light);
     analogWrite(l,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=255 ;light > 0; light--)
  {
     analogWrite(x,light);
     analogWrite(i,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=255 ;light > 0; light--)
  {
     analogWrite(e,light);
     analogWrite(t,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=255 ;light > 0; light--)
  {
     analogWrite(r,light);
     analogWrite(l,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
}

void OutsideIn()
{
  ClearAll();
  for(int light=0;light < 255; light++)
  {
     analogWrite(l,light);
     analogWrite(r,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=0;light < 255; light++)
  {
     analogWrite(e,light);
     analogWrite(t,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=0;light < 255; light++)
  {
     analogWrite(x,light);
     analogWrite(i,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=255 ;light > 0; light--)
  {
     analogWrite(l,light);
     analogWrite(r,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=255 ;light > 0; light--)
  {
     analogWrite(e,light);
     analogWrite(t,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
  for(int light=255 ;light > 0; light--)
  {
     analogWrite(x,light);
     analogWrite (i,light);
      buttonVal = digitalRead(buttnPin);
 if(buttonVal == LOW)  {buttonPress++;}
     delay(2);
  }
}


Will show more as I get it up here.

Friday, June 29, 2012

How to solder 101

Browsing the interwebz today I was pondering the Raspberry Pi website (I want one so bad, but I really need to try to do a few other projects first) and came across this wonderfully informative comic book on soldering.

Soldering knowledge is key in any electronics project. You can use soldering skills to harvest extra parts from broken/free pieces of tech laying around, and it is definitely key when you try to build your own project on a board.


The MightyOhm site is hosting the comic book, and they also have many translations of the book as well!

Check it out: http://mightyohm.com/blog/2011/04/soldering-is-easy-comic-book/

Thursday, May 17, 2012

Real delay() and how to use it.

We have all seen the posts about the header files to bring the ease of use of the Arduino to the Launchpad/MSP430 series chips, however one thing that I have found about this that you DO NOT have to have libraries for.....

delay! Yes folks! Delay IS in the realm of possiblility for you folk coming from the Arduino IDE to CCS/GCC. There is only a few small differences you have to know about it.

1. It's not delay(); it's _delay_cycles()
2. The time given in _delay_cycles(x) is NOT in milliseconds per-say based on time. Its based on the speed of the microcontroller, so if you have a chip set for 16mhz, that's 16,000,000 cycles per second. That's mighty fast. If we divide 16,000,000 cycles by 1000 milliseconds, we get: 16,000 cycles per millisecond. So therefore, each millisecond will be a multiple of 16,000. Oh sounds like a pain in the tuccas eh? Well... There is over the counter medication for that, but for the issue at hand here we will clean it up by creating a function in code! (in the brain of course... this is actually less efficient for the micro but not by much really).


/ Delays by the specified Milliseconds
//Justifiably ripped straight from http://www.threadabort.com/?p=26 Mad propellers to that person.
void delay(unsigned int ms)
{
while (ms–)
{
__delay_cycles(16000); // set for 16Mhz change it to 1000 for 1 Mhz
}
}


With this in our hands, we have some serious power here. Basically, we can now address a delay in code for the micro in ms and it will work as it should.

Also let me show this in one line, for your copy/pasting needs :)


void delay(unsigned int ms){while (ms–){__delay_cycles(16000);}}

Remember, all code in c is ensured to end the line with a semicolon (;) EXCEPT for when we are commenting (//stufstufstufetc). So since I have taken out the comment for changing the delay in clocks compaired to speed for timing, it all fits in one line and will keep you (semi) sane through the coding process :)


Just to go ahead and throw an alternative out there, here is a different way we can make a void function:

void delay(int n){int i;for(i = 0; i < n; i++){_delay_cycles(16000);}}

Now mind you, this version is probably not as accurate as the first one, however the same thing is happening. For simple projects involving nothing more than a flashing light or two this will do for any timing that you need on the micro. However as we will find out later, this will not suffice when it comes to having multiple things going on at once.

The big value of this function is it can take care of a lot of your delay needs AS LONG AS you have the delay cycles number correct for the speed it is running at.

Here is le' free app o-teh-day.

/*2 line Insta-Delay on MSP430 Launchpad
 * Free as in free coffee! <|0.o|>
 * Hardware Hacking Honkey 2012
*/

#include  <msp430g2553.h>
void delay(int n);

void delay(int n){int i;for(i = 0; i < n; i++){_delay_cycles(16000);}}

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
  BCSCTL1 = CALBC1_16MHZ;   //set speed of chip to 16mhz
  DCOCTL = CALDCO_16MHZ;    //set speed of chip to 16mhz
  P1DIR |= 0x01;            // Set P1.0 to output direction
  P1DIR |= 0x40;            // Set P1.6 to output direction
  P1OUT &=~ 0x40; //Start off turning on P1.6 so it will go back and fourth right.
  for (;;)
   {
    P1OUT ^= 0x01; //toggle P1.0 on and off
    P1OUT ^= 0x40; //toggle P1.6 on and off
    delay(1000);   //your delay for exactly one second, sir!
   }
}

Saturday, May 12, 2012

Proper documentation on the TI Launchpad found in the wild! 0.o

The whole reason I started this blog was to help new folks that are starting with the TI Launchpad or jumping ship from Arduino to Launchpad. This is because of all the random stuff that is out there that is not very helpful for the beginner, HOWEVER.. Today browsing the interwebs, I came across this wonderful document..

The Getting Started with the MSP430 Launchpad Student Guide and Lab Manual:
http://software-dl.ti.com/trainingTTO/trainingTTO_public_sw/MSP430_LaunchPad_Workshop/LaunchPad.pdf

I stumbled onto this document while browsing Element 14 which is an excellent website on the hobby front: http://www.element14.com/community/groups/msp430-ultra-low-power-microcontrollers/blog/2012/04/11/msp430-16bit-launchpad-valueline-workshop

This is a MUST for beginners to grab and to get started on the launchpad. I myself will be going through this and am liking what I have been browsing so far. It really helps for learning the basics.

Thursday, May 10, 2012

Time for some software PWM on the Launchpad!

So! You want to do some PWM lighting magic on the launchpad, but do not feel like getting into the whole spookyness of messing with the timers (or the watchdog timer since we are on the subject)? Well, to side step that, we can take for instance software to do this magic for us.

What is PWM you may ask yourself? PWM stands for Pulse Width Modulation, and in laymans terms it really ends up for the instance of lighting leds, a way of blinking them in a fashion that makes it look like it brightens or dims the led. You have to use PWM if you want leds to flicker or dim.

Why do it this way? Well first we need to look at some rather drab (but required) information on lighting leds.
Figure 1
Figure 2










In Figure 1 we have the schematic symbol for an LED. First thing you need to know is that on the left side of this schematic, leg 1 is short, which on an actual LED will always indicate negative (Rather it indicates more than that, but that's out of the scope of this discussion. We will get into that as I get deeper into this blog). Leg 2 on the other hand, indicated positive. This is characteristic of ALL leds.

In Figure 2, we have another led, but this time in a circuit. I have no idea if that value of resistor is correct to properly light an LED, but I know it will work. In my experience, most information out there will tell you to use a resistor on the positive end of the LED (and do so for each LED), however what I like to do, is multiply the resistance needed by the amount of LEDS you need to light, and use ONE resistor on the ground side. Also as a side note, I ONLY do this in prototyping. I don't recommend this for production, or once you solder your stuff on a board, just because well... The professionals say not to, so I wouldn't risk it for fear that you finally get the darned thing together, and then a week later your leds start burning out because of too much, or not enough resistance to each led which would entail you having to pull the solder from the board, and replacing the leds and then it may be too late to add the proper leds...

Now back to PWM! Watch the video!



This is a real crappy example just fyi, but it's simple. This was done with an Arduino, but it's the same concept. Only in this version, the light blinks, and we only see a line where it's lit which makes the text shown. If this were standing still, you would only see the lights brightening and dimming.

The reason why you can't just cut power down to an LED is that it simply wont work... Well it will.... for about a minute, and then you will have a smoked/broken LED. Worthless really.

So as a way to get it to 'dim' for our human eyes, we simply make them blink on for a moment, and then turn off for a moment that makes our eyes think it's dim, because our eyes actually cant judge the speed that the LED is lighting.

Here is what LED PWM looks like in software(for TI launchpad gcc. Replace P1OUT with DDRB for Atmel gcc):

int i = 0;
int a = 1000;

for(i = 0; i < a; i++) {
  P1OUT |= 0x01;}
for(i = 0; i < a; i++) {
  P1OUT &=~ 0x01;}
 a--;
if(a <10){a = 1000;}

In this example, P1.0 will light for 1000 clock cycles and then will turn off for 1000 clock cycles. After each sequential light up and turn off, the light will stay on and off for a -1 clock cycles. Once a is 9 or less, a will be returned to 1000, and the sequence will start over again. This (should) result in the led going from bright to dark and once the sequence finishes, the led will start back at the brightest it can get and dim back down.

PWM in software is a GREAT way to learn about a lot of different things with programming and lighting leds and using microcontrollers that I feel is a much better step forward after the "light for one second, turn off for one second hello world" application, because this is something that makes you go ooooo, instead of looking at the code to light the led, and after the honeymoon phase of going oooh, I made it light up!

Whoops! Forgot to add the code for this post! Sorry bout that. Here it is:


/*pwm_software.c
 * Software PWM example
 * Free as in free coffee! <|0.o|>
 * Hardware Hacking Honkey 2012
 * http://honkeyhacker.blogspot.com/
 * No external hardware needed, just the launchpad board.
*/

#include  <msp430g2553.h>

void main(void) //Main for loop for the cause
{
 WDTCTL = WDTPW + WDTHOLD;  // Stops the Watch Dog Timer(WDT)
 P1DIR |= 0x01;             // Sets P1.2 to output
 P1DIR |= 0x40; // Sets P1.6 to output
 int a = 1000; //on time for P1.2, off time for P1.6
 int b = 0; //on time for P1.6, off time for P1.2
 int flip = 0; //variable we will use to change pwm brightening and darkening
 int i = 0; //variable used in for loops.
for(;;) //For loop to infinity and beyond
{
for(i=0;i<a;i++){} //for loop wastes time
P1OUT |= 0x01; //turn on P1.2
P1OUT &=~0x40; //turn off P1.6
    for(i=0;i<b;i++){} //for loop wastes some time
    P1OUT &=~0x01; //turn off P1.2
    P1OUT |= 0x40; //turn on P1.6
    if(flip==0){a=a-2;b=b+2;} //if flip = 0, decrement time P1.2 is on and increment time P1.6 is on
    if(flip==0 && a<0){flip=1;} //if P1.2 is on all the way, and P1.6 is off, then let's go backwards
    if(flip==1){a=a+2;b=b-2;} //if flip = 0, decrement time P1.6 is on and increment time P1.2 is on
    if(flip==1 && a>1000){flip=0;} //if P1.6 is on all the way, and P1.2 is off, then let's go forwards
    if(flip==0 && a > 800){a=a-2;b=b+2;}   //used to speed up lighting 1.2 and dimming 1.6 in the beginning
    if(flip==1 && b > 800){a=a+2;b=b-2;}   //used to speed up lighting 1.6 and dimming 1.2 in the beginning
}
}

Wednesday, May 9, 2012

More about me, and the nicer side of the TI launchpad

After yesterday's post, I wanted to give my softer side of things on this really cool little tool. Yes I trashed TI for having terribly jumbled blocks of how to info, but there is definitely some gold to be had here in this kit and these stupid cheap chips. Here are my feelings about it and why I am going to be using this platform a lot in the coming random projects I have going on.

Atmega chips
Positives:
  • Very powerful 
  • ALL CHIPS are feature rich in some way shape or form
  • Easy to program
  • Lots of program space
  • Premade PCB's galore to purchase or make yourself
  • Premade drop on modules galore to purchase or make yourself.
  • No code size limitations on most any IDE/compiler combo you get.
  • Very well documented, and usually in terms that is easy for beginners to understand
Negatives:
  • Pain in the butt to make a stand alone chip because of multiple components required to make it work.
  • Much more expensive all around
  • Even more expensive to obtain a proper programmer.
  • If offboarding from arduino (or purchasing chips without the arduino bootloader pre-flashed) you MUST use an offboard oscillator to program the chip or else it wont work.
TI chips
Positives:
  • Easy to offload the chip. 
  • Minimal connections to use spy-by-wire (only 1 resistor pulling reset up needed).
  • The dev platform @ $4.30. I mean aside from the chips themselves, this is awesome. You don't have to worry about purchasing an expensive FTDI chip. Heck, you can buy and throw a whole Launchpad in each embedded project if you want cause it's cheaper than purchasing an atmega chip and complimentary components to make it run!. Heck it's cheaper than most atmega chips by themselves!
  • Fairly Speedy chips (good enough for most random diy stuff that isn't speed critical)
  • CANNOT BRICK THE CHIP! No crossing your fingers hoping you dont flip the wrong fuse bits.
  • CHEAP!!! Like uber cheap. Cheap is champ around these parts just fyi.
  • If using gcc to compile applications, there is no code size limit
Negatives:
  • Harder to program than with using the supplied libraries in the arduino IDE.
  • Smaller memory size
  • Using chips with memory sizes larger than 16k requires purchasing a license for Code Composer Studio IDE, and 4k when using IAR Embedded Workbench.
  • Random mishmash of knowledge makes a larger learning curve for the beginner.
Now mind the idea that TI is way cheaper and a (on pcb anyway) way easier to use than the atmega series, I am itching to use these in my coming projects.

Tuesday, May 8, 2012

Beginning TI Launchpad

Welcome back!!!


Obviously since the first post didn't annoy you, I will try once again. This time however, I am talking not about me but about the TI launchpad. This is a very interesting little board, and I am sure you have already seen people talk about it here and there, especially on the negative side of things, but let me start off by saying....


HOLY GOD TI, WHAT THE HELL WERE YOU THINKING!?


Not about the hardware mind you, I find that these chips and the whole combo deal for $4.30/piece are one hell of a deal. Unfortunately what I do not understand is the LACK OF DOCUMENTATION for the 'hobbiest'. Now mind you if you have a bachelor's or doctorates in electrical engineering, or something then you  are probably reading this and saying 'oh god, what a prick! he doesn't know what he's saying!!'. Unfortunately I do not hold any of those things. I have a dual associates degree (soft toilet paper version at least) in computer programming and networking.


Well....


Even with this and a CCNA under my belt, I have to say this is the most ridiculous random crap splatter of documentation I have ever seen. Especially for beginners and hobbiests. Sure you may be able to read all about electrical characteristics of XYZ power by means of some crazy math that will make your brain melt, BUT YOU JUST WANNA START TOGGLING LEDS BESIDES THE ONES IT CAME WITH!


In my experience with Atmega controllers and interfacing in avr-gcc, it's pretty well documented that you address the ports and pins by hex or you can do so by binary as shown:
DDRB |= 0x00000001 (output pin 1)
DDRB  |=  0x01 (output pin 1)
DDRB  |=  0x00000010 (output pin 2)
DDRB  |=  0x02 (output pin 2)
DDRB  |=  0x00000011 (output pins 1 and 2)
DDRB  |=  0x03 (output pins 1 and 2)
and so on...

In the examples TI give you about interfacing to digital pins, they only show you how to light the two pins that are built onto the dev board as shown below:


//******************************************************************************
//  MSP430G2xx3 Demo - Software Toggle P1.0
//
//  Description; Toggle P1.0 by xor'ing P1.0 inside of a software loop.
//  ACLK = n/a, MCLK = SMCLK = default DCO
//
//                MSP430G2xx3
//             -----------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//            |             P1.0|-->LED
//
//  D. Dang
//  Texas Instruments, Inc
//  December 2010
//   Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************

#include  <msp430g2553.h>

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  P1DIR |= 0x01;                            // Set P1.0 to output direction
  P1DIR |= 0x40;
  long i = 50000;
  for (;;)
  {
    i = 50000;
    P1OUT |= 0x01;                          // Toggle P1.0 using exclusive-OR
    P1OUT &=~0x40;
    do{i--;}while(i>0);
    i = 50000;
    P1OUT |= 0x40;                          // Toggle P1.6 using exclusive-OR
    P1OUT &=~ 0x01;
    do{i--;}while(i>0);
  }
}
//************************Code modified by me to bounce lights back and fourth***************
//********************Caution. I can't remember if this works right or not. *********************

Anyways with this example code, you can see that interfacing pins 1.2 and 1.6 are as follows:
    P1OUT |= 0x01;                          // Toggle P1.0 using exclusive-OR
    P1OUT |= 0x40;                       // Toggle P1.0 using exclusive-OR
So we can now depict that P1.0 = 0x01, and P1.6 = 0x40...

Now what? What about 1.1, 1.2, 1.3, etc. etc. etc?

I FOUND NOTHING ON THIS by digging all around the internet until just about an hour ago when coming across this video:


Awesome, yes that they finally explain the pin scheme, however it would be extremely nice to add that SOMEWHERE in the documentation instead of randomly finding it in a youtube video (except the guy in this video as well... he allegedly works for TI so, I suppose he knows his stuff). Mind you maybe I am just an old fuddy dud and care more to read the info on it than to watch poorly shot youtube videos of people who may or may not even know what they are talking about on such issue, but I (Finally) digress... ON WITH THE SHOW!

So from this we learn that to reference the pins on the TI chips, you do so whereby the pin number translated literally into hex:

P1.0 = P1OUT |= 0x00000001 or |= 0x01
P1.1 = P1OUT |= 0x00000010 or |= 0x02
P1.2 = P1OUT |= 0x00000100 or |= 0x04
P1.3 = P1OUT |= 0x00001000 or |= 0x08
P1.4 = P1OUT |= 0x00010000 or |= 0x10
P1.5 = P1OUT |= 0x00100000 or |= 0x20
P1.6 = P1OUT |= 0x01000000 or |= 0x40
P1.7 = P1OUT |= 0x10000000 or |= 0x80
P2.0 = P2OUT |= 0x00000001 or |= 0x01
P2.1 = P2OUT |= 0x00000010 or |= 0x02
P2.2 = P2OUT |= 0x00000100 or |= 0x04
P2.3 = P2OUT |= 0x00001000 or |= 0x08
P2.4 = P2OUT |= 0x00010000 or |= 0x10
P2.5 = P2OUT |= 0x00100000 or |= 0x20

Also....
I just found out these pins can be set high through useing 'BIT0', etc. as shown:

P1OUT |= BIT0; //Pin 1.0
P1OUT |= BIT1; //Pin 1.1
P1OUT |= BIT2; //Pin 1.2
P1OUT |= BIT3; //Pin 1.3
P1OUT |= BIT4; //Pin 1.4
P1OUT |= BIT5; //Pin 1.5
P1OUT |= BIT6; //Pin 1.6
P1OUT |= BIT7; //Pin 1.7
P2OUT |= BIT0; //Pin 2.0
P2OUT |= BIT1; //Pin 2.1
P2OUT |= BIT2; //Pin 2.2
P2OUT |= BIT3; //Pin 2.2
P2OUT |= BIT4; //Pin 2.2
P2OUT |= BIT5; //Pin 2.2
P2OUT |= BIT6; //Pin 2.2

Therefore....
Here is a program to blink ALLLLLLL PINNNNSSS in wonderful Cylon fashion :)


/*1 way cylon (not back and fourth) on MSP430 Launchpad
 * Free as in free coffee! <|0.o|>
 * Hardware Hacking Honkey 2012
*/

#include  <msp430g2553.h> //switch to whatever you use. Also remove the pins if they are not populated by the chip

void main(void) //Main for loop for the cause
{
 WDTCTL = WDTPW + WDTHOLD;  // Stops the Watch Dog Timer(WDT)
 P1DIR |= 0x01;             // Sets P1.0 to output
 P1DIR |= 0x02;             // Sets P1.1 to output
 P1DIR |= 0x04;             // Sets P1.2 to output
 P1DIR |= 0x08;             // Sets P1.3 to output
 P1DIR |= 0x10;             // Sets P1.4 to output
 P1DIR |= 0x20;             // Sets P1.5 to output
 P1DIR |= 0x40;             // Sets P1.6 to output
 P1DIR |= 0x80;             // Sets P1.7 to output
 P2DIR |= 0x01;             // Sets P2.0 to output
 P2DIR |= 0x02;             // Sets P2.1 to output
 P2DIR |= 0x04;             // Sets P2.2 to output
 P2DIR |= 0x08;             // Sets P2.3 to output
 P2DIR |= 0x10;             // Sets P2.4 to output
 P2DIR |= 0x20;             // Sets P2.5 to output
 int i = 0; //variable used in for loops.

for(;;) //For loop to infinity and beyond!!!!!!
{
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT |= 0x01; //Output P1.0
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x01; //Stop output on P1.0
P1OUT |= 0x02; //Start output on P1.2
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x02; //Stop output on P1.2
P1OUT |= 0x04; //Start output on P1.3
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x04; //OMG your still reading these comments?  P1OUT |= 0x08;                                                     //0.p
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x08;
P1OUT |= 0x10;
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x10;
P1OUT |= 0x20;
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x20;
P1OUT |= 0x40;
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x40;
P1OUT |= 0x80;
for(i=0;i<10000;i++){} //for loop wastes time
P1OUT &=~ 0x80;
P2OUT |= 0x01;
for(i=0;i<10000;i++){} //for loop wastes time
P2OUT &=~ 0x01;
P2OUT |= 0x02;
for(i=0;i<10000;i++){} //for loop wastes time
P2OUT &=~ 0x02;
P2OUT |= 0x04;
for(i=0;i<10000;i++){} //for loop wastes time
P2OUT &=~ 0x04;
P2OUT |= 0x08;
for(i=0;i<10000;i++){} //for loop wastes time
P2OUT &=~ 0x08;
P2OUT |= 0x10;
for(i=0;i<10000;i++){} //for loop wastes time
P2OUT &=~ 0x10;
P2OUT |= 0x20;
for(i=0;i<10000;i++){} //for loop wastes time
P2OUT &=~ 0x20;
}
}