Search code examples
serial-portarduinohardware-interface

Serial Data with Arduino


I am just starting to learn about the Arduino. I have a 1 meter LED strip from Radio Shack to play around with.

The strip came with a sample program so I looked at it and whittled it down to the basics, but I don't understand what's going on. I am looking for someone to explain what is going on and how the functional code works.

Here's the code:

#include <avr/pgmspace.h>

#define DATA_1 (PORTC |=  0X01)
#define DATA_0 (PORTC &=  0XFE)
#define STRIP_PINOUT (DDRC=0xFF)

/*
green 0xff0000
cyan 0xff7f00
truquoise 0xffff00
dark blue 0x00ff00
red 0x0000ff
dark yellow 0x6f00ff
yellow 0x8f00ff
white 0xffffff
off white 0x444444
dim white 0x111111
off 0x000000
*/

PROGMEM long test[10][10]={
  {0x000000,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x000000,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x000000,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x000000,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x000000,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x000000,0x00ff00,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x000000,0x00ff00,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x000000,0x00ff00,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x000000,0x00ff00},
  {0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x000000},
};

void setup() {

  STRIP_PINOUT;

  reset_strip();

}


void loop() 
{
  while (1)
  {
    send_pattern(test, 10, 50);
    reset_strip();
  }
}


void send_pattern(long data[][10], int length, int rate)
{
  int i=0;
  int j=0;

  for (i=0; i<length; i++)
  {
    noInterrupts();
    for (j=0; j<10; j++)
    {
      send_strip(pgm_read_dword_near(&data[i][j]));
    }
    interrupts();

    delay(rate);

  }




}


void send_strip(uint32_t data)
{
  int i;
  unsigned long j=0x800000;

  for (i=0;i<24;i++)
  {
    if (data & j)
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");    
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      DATA_0;
    }
    else
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");    
      DATA_0;
    }

    j>>=1;
  }
}


void reset_strip()
{
  DATA_0;
  delayMicroseconds(20);
}

Solution

  • That code is not a good place to start if you don't know C and/or haven't used an Arduino before.

    The Arduino programming language (called Wiring) abstracts lots of the raw details of the C code into more simplified formats (and/or language) so that it is easier for beginners to make progress with their ideas and not get stuck in "becoming programmers." The Wiring code gets interpreted to C code before compiling which enables users to mix C (and C++) with Wiring in one sketch.

    Your code above is mixing C and Wiring syntax so you won't find all the info about the syntax in the Arduino docs but it is worth searching on keywords or terms you don't understand. The big thing that is done differently involves setting up and using the serial port. See the Arduino docs for Serial to see how it is done there (and how much simpler it is to understand).

    I'll take a crude stab at describing the functionality (before I get too bored)...


    This line defines a variable (in PROGMEM - EEPROM memory) named test as a 10 x 10 array of numbers (longs): e.g. there are 10 arrays and each one contains 10 numbers (in hexidecimal notation)

    PROGMEM long test[10][10]={
    

    This block calls a function (#defined at the top of the code) to set a port) and a function (at the bottom of the code) to reset the strip.

    void setup() 
      STRIP_PINOUT;
      reset_strip();
    }
    

    void loop() 
    {
      while (1) // i.e. do this forever
      {
        // send the test var, its length and the delay amount between each pattern
        send_pattern(test, 10, 50); 
        reset_strip();
      }
    }
    

    This function iterates through the passed var data (which is in this case the var 'test'), read the value in the array at position [i][j] using an AVR function called pgm_read_dword_near and sends that value to the function send_strip which sends it out the serial port. After each array is sent, it calls delay() to wait for the number of milliseconds defined in rate.

    void send_pattern(long data[][10], int length, int rate)
    {
      int i=0;
      int j=0;
    
      for (i=0; i<length; i++)
      {
        noInterrupts();
        for (j=0; j<10; j++)
        {
          send_strip(pgm_read_dword_near(&data[i][j]));
        }
        interrupts();
    
        delay(rate);
    
      }
    }