Show Posts
Pages: [1]
1  Forum 2005-2010 (read only) / Bugs & Suggestions / Re: Higher Performance IO on: July 26, 2008, 02:59:36 pm
 
Quote
It still seems like there should be a safe (nicely integrated in the Arduino environment) faster version of shiftOut() available for general Arduino use, would you agree?  I can't help but wonder how many Arduino users simply gave up performing serial IO with software because they thought they were limited to a slow shiftOut() implementation and did not have the expertise to code up a faster version.

I agree and it should have the ability to designate whether the clock pin idles high or low.

I had to write my own shiftOut to get the clock to idle high and I suffered a glacially slow new function - each clock cycle was taking 14uS. Re writing as a Port manipulation improved to 3uS. I didn't know about macros and the compiler interpretation issues brought up here.

But my devices can clock at 20MHz so I am looking at using SPI (didn't know about that until someone here told me). It seems promising. My only problem with that is my device only uses 2 wires and strobes the chips by holding the clock high and pulsing the data line 8 times. I might have to disable the SPI when I need t do this or maybe multiplex the clock and data lines so I can drive them with both the SPI and some other pins to send the strobe signal.

But basically I agree that a faster shiftOut would be great - lots and lots of people are trying to shiftOut to LED arrays and end up finding the Arduino a bit pokey at this.

Martin, cant you divide the SPI clock/4 to get to 4MHz so tha SPI would work with your 5MHz devices?
2  Forum 2005-2010 (read only) / Interfacing / Re: Arduino and 1-wire on: April 17, 2008, 04:18:16 pm
Has anyone had any problems with this library in Arduino-0011?

I am trying to interface to the 1-wire weather station and am just initially trying to access the ds1820 temperature sensor. But when I try the sample code provided with the library it can't seem to find any addresses. If I comment out the search part and enter the address manually it does return a presence pulse but all zeros for the temperature and 0 for the crc

This is exactly what it returns : R=10 A 36 9 0 8 0 C9 P=1 0 0 0 0 0 0 0 0 0  CRC=0

I'm not very good at understanding the code and maybe I've jumped into deep water but the wiring I2C library was so easy, I kind of expected the same here...

Thanks,
3  Forum 2005-2010 (read only) / Interfacing / Re: Shift Out speed issue on: July 17, 2008, 02:55:07 pm
It works for a bit then hangs up in the SPIF loop apparently with the write collision flag set and the SPIF unset. I don't know why. Thought maybe sending ints to spi_transfer was the problem. I forced the char type on everything (all the examples use char in the spi_transfer function - not sure why) but that did not help the problem. Maybe I did that wrong though.

Code:
/*  This is a speed test of sending a fade waveform (envelope) through a string of x16 LED Dotz
*
*
*Uses LED X-16 Dotz by Lighting Science which is based on cascading DM412 LED driver chips by
*Silicon Touch Technology.
*Sends 48 bits of RGB PWM data to each Dotz in string, clock held high after last bit
*and internal strobe initiated by pulsing data 8 times
*
*Uses hardware spi to shift out pwm commands to DM412s
*
*/
#define DATAOUT 11//MOSI - Hardware SPI
#define SPICLOCK  13//sck

#define stepResolution 8        //the number of steps between off-on-off
#define segment_length 10    //the length of the light strings

int offset = 5;      //lower the offset the more Dots simultaneously illuminated, will be related to windspeed
byte clr;

int unsigned long time = 0;

int light[segment_length];  //the array of structs containing values to output and where to send them

void setup()
{
  Serial.begin(19200);
  Serial.println("setup");
  pinMode(DATAOUT, OUTPUT);
  pinMode(SPICLOCK,OUTPUT);
  
  // SPCR = 01011000
  //interrupt disabled,spi enabled,msb 1st,master,clk high when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL);
  clr=SPSR;
  clr=SPDR;
  //SPSR = 00000001
  //double clock speed, thus clock/2
  SPSR = (1<<SPI2X);
  
  int segment_number = 0;
  // initialize the light array
    for (int i=0; i < segment_length; i++) {
        light[i] = 0;        //initialize all values to 0
    }
}


void loop()  {
  int fade_increment = (255 / stepResolution);
  int head_position = 0;    //the leading edge of the waveform
  int old_head = 0;
  
  time = millis();
  //^^^^^^^^^^^^^^^^^^^^^^^^ outside loop ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  for (int i = 0; i < ((segment_length + (stepResolution / 2)) * offset) ; i++) {
        
    //********** inner loop ************** output to to 2 segments ********************************************
    for (int j =0; j < segment_length; j++) {
      if ((j == head_position) and (light[j] == 0)) {    //if light[j] is the head and not already active, turn it on
        light[j] = 255;            //light has to be 0 because head_position dwells on one number for a time
      }
            
      spi_transfer(light[j]);    //shift it out to the lights - R
      spi_transfer(light[j]);    //shift it out to the lights - G
      spi_transfer(light[j]);    //shift it out to the lights - B
      
      if (light[j] > 0) {
        light[j] = max(light[j] - fade_increment, 0);  //value decreased by fade increment but not less than 0
      }
    }  //******************************* end - inner loop ******************************************************
    
    sendStrobe();    //tell the LEDs to latch in values and display
    Serial.println();

    old_head = head_position;
    if ((i % offset) == 0) {      //if i is evenly divisible by offset
      head_position++;    //increment head_position to by one (ie. next light in string)
    }
  }  //*********************** end of outside loop *****************************************************************************
  time = (millis() - time); // / 1000);
  Serial.print("time = ");
  Serial.println(time);
}

char spi_transfer(volatile byte data)
{
  Serial.print(data, DEC);
  Serial.print(":");
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait for the end of the transmission
  {Serial.print (SPSR, BIN);
  Serial.print(", ");
  };
  return SPDR;                    // return the received byte
}

void sendStrobe()
    //sequence to trigger internal strobe of the Dotz (DM412) - 8 pulses on data
{
  for (int j=0; j < 8; j++)  {
   PORTB |= B00001000;    //MUCH faster than digital writes
   PORTB &= B11110111;   //pin 11 toggles hi- low 8 times leaves low - this will have to be changed to toggle the appropriate data pin
  }
}

4  Forum 2005-2010 (read only) / Interfacing / Re: Shift Out speed issue on: July 17, 2008, 03:47:34 am
Thanks for the SPI lead. It looks like just the ticket. I wrote something tonight. I seem to hang up in the while SPIF loop because the write collision (WCOL) flag is getting set. I'll have to debug it tomorrow...
5  Forum 2005-2010 (read only) / Interfacing / Re: Shift Out speed issue on: July 16, 2008, 01:25:36 pm
Here is the code.

Code:
/*  This is a speed test of sending a fade waveform (envelope) through a string of x16 LED Dotz
*
*Uses LED X-16 Dotz by Lighting Science which is based on cascading DM412 LED driver chips by
*Silicon Touch Technology.
*Sends 48 bits of RGB data to each Dotz in string, clock held high after last bit
*and internal strobe initiated by pulsing data 8 times
*
*This does not use the arduino native shiftOut command but a written shiftout
*instead that keeps the clock pin high when idle.
*/

#define stepResolution 16        //the number of steps between off-on-off
#define segment_length 20    //the length of the light strings

int offset = 5;      //lower the offset the more Dots simultaneously illuminated, will be related to windspeed

int clockPin = 12;    //PORT B pins 8 - 13
int dataPin1 = 11;    //to shift data out to a light string
int dataPin2 = 10;
int dataPin3 = 9;
int dataPin4 = 8;

int unsigned long time = 0;

struct Dotz {    //a structure with...
  int value;      //value to output
  int segment;    //segment to output to
};
struct Dotz light[segment_length];  //the array of structs containing values to output and where to send them

void setup()
{
  Serial.begin(19200);
  Serial.println("setup");
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin1, OUTPUT);
  pinMode(dataPin2, OUTPUT);   //not used currently but will be used as part of multiple segment strategy
  
  int segment_number = 0;
  // initialize the light array
    for (int i=0; i < segment_length; i++) {
        light[i].value = 0;        //initialize all values to 0
      light[i].segment = 1;
          }
}

void loop()  {
  int fade_increment = (255 / stepResolution);
  int head_position = 0;    //the leading edge of the waveform
  int old_head = 0;
  
  time = millis();
  //^^^^^^^^^^^^^^^^^^^^^^^^ outside loop ^^^
  for (int i = 0; i < ((segment_length + (stepResolution / 2)) * offset) ; i++) {
        
    //********** inner loop ************** output to to 2 segments ***
    for (int j =0; j < segment_length; j++) {
      if ((j == head_position) and (light[j].value == 0)) {    //if light[j] is the head and not already active, turn it on
        light[j].value = 255;            //light has to be 0 because head_position dwells on one number for a time
      }    
      RGBout(light[j].segment, (light[j].value<<8), (light[j].value<<8), (light[j].value<<8));    //shift it out to the lights
      if (light[j].value > 0) {
        light[j].value = max(light[j].value - fade_increment, 0);  //value decreased by fade increment but not less than 0
      }
    }  //******************************* end - inner loop ***
    sendStrobe();
    old_head = head_position;
    if ((i % offset) == 0) {      //if i is evenly divisible by offset
      head_position++;    //increment head_position to by one (ie. next light in string)
    }
  }  //*********************** end of outside loop *
  time = (millis() - time); // / 1000);
  Serial.print("time = ");
  Serial.println(time);
}
  
void RGBout (int segment, int r, int g, int b)
      //shifts rgb values out most significant bit first by sending bytes to shiftOut command      
      // " >> " is bitshift operator - moves top 8 bits (high byte) into low byte
{
  int pinMask = 0;
  //Serial.print(segment);
  switch (segment) {
    case 1: pinMask = B00001000;        //data pin 11
            //clockMask = B11101111;  //clock pin 12
            break;
    case 2: pinMask = B00000100;        //data pin 10
            //clockMask = B11011111;  //clock pin 13
            break;
    case 3: pinMask = B00000010;        //data pin 9
            //clockMask = B11011111;  //clock pin
            break;
    case 4: pinMask = B00000001;        //data pin 8
            //clockMask = B11011111;  //clock pin
    default:pinMask = B00000001;        //data pin 8
            //clockMask = B11011111;  //clock pin
  }
  
  shiftOutClkHi(pinMask, clockPin, (r >> 8));    // shift out highbyte - RED
  shiftOutClkHi(pinMask, clockPin, r);    // shift out lowbyte - RED
  
  shiftOutClkHi(pinMask, clockPin, (g >> 8));  // shift out highbyte - GREEN
  shiftOutClkHi(pinMask, clockPin, g);    // shift out lowbyte - GREEN
  
  shiftOutClkHi(pinMask, clockPin, (b >> 8));  // shift out highbyte - BLUE
  shiftOutClkHi(pinMask, clockPin, b);    // shift out lowbyte - BLUE
}

void sendStrobe()
    //sequence to trigger internal strobe of the Dotz (DM412) - 8 pulses on data
{
  for (int j=0; j < 8; j++)  {
   PORTB |= B00001000;    //MUCH faster than digital writes
   PORTB &= B11110111;   //pin 11 toggles hi- low 8 times leaves low - this will have to be changed to toggle the appropriate data pin
  }
}

void shiftOutClkHi(int pinMask, int myClockPin, byte myDataOut) {
 // This shifts 8 bits out MSB first, on the rising edge of the clock,
  //then clock idles high. Bitmasks myDataout by anding the value with a 1
  //by i places then puts that result on myDataPin using Port Manipulation
  
  int clockMask = B11101111;  //bit mask for port write to clock pin
  
        for (int i = 0; i < 8; i++)  {  //compares each bit by masking it w/ all 0s and one 1
                if (myDataOut & (1 << (7 - i))){  //shifts 1 left by 7-i places
                  PORTB |= pinMask;}
                else {PORTB &= ~pinMask;}      
                PORTB &= clockMask;  //fast way to toggle clock low then hi
                PORTB |= ~clockMask;  
      }
}

6  Forum 2005-2010 (read only) / Interfacing / Shift Out speed issue on: July 16, 2008, 01:24:27 pm
Hello,

I have written a bit of code to use a string of RGB LEDs that utilize a cascading string of shift registers (DM412 by Silicon Touch Technology). Each shift register takes 6 bytes to control the RGB value of the LED connected to it. It will pass the bits down the line every clock pulse until I send it a strobe code (8 pulses on the data pin).  My eventual goal is to have a chase of 300 lights, 2" apart,  that will move at the same rate as the wind. The chase will ramp each LED up then down in brightness rather than just blink on and off the LED.

I had to write my own ShiftOut because I needed the clock line to idle high. But other than that, I have been pretty successful in controlling the LED string. The problem I am having is that the Arduino cannot seem to shift out fast enough to approximate more than a gentle breeze.  In fact sending a ramping signal to just 20 lights takes 383ms.  This translates, I believe, into 150kbits/s. Does this seem slow?  This is 100 clock cycles for each bit shifted out.

Thanks for your help. I'll have to post my code separately...

7  Forum 2005-2010 (read only) / Interfacing / Re: Around 50 RGB Leds... Possible??? on: May 07, 2008, 12:33:14 am
Julienb,

you might look at 3 chips that I have found. One is the allegro A6280 3-Channel Constant-Current LED Driver with Programmable PWM Control http://www.allegromicro.com/en/Products/Part_Numbers/6280/index.asp
The other is Silicon Touch Technology DM413 http://www.siti.com.tw/product/spec/LED/DM413.pdf also their DM412. http://www.e-neon.ru/user_img/catalog_datasheets/dm412-a.003.pdf

I am doing a project that uses the DM412 and have found it relatively easy to interface. Each RGB LED is driven by a DM412. You shift out 48bits for every LED you have in your line and either toggle the strobe line or send a special software strobe by holding the clock high and sending 8 pulses on the data line.

I see that Digikey and Newark sell the Allegro chip but only in the qfn package. Sparkfun soldering tutorials have encouraged me that surface mount is possible but I have yet to tackle that.

The DM412 I am using is in a commercial LED product that I am hacking. The company engineers told me that is what is in it. I'm not sure they want me broadcasting this info. Besides they charge $10 a node for their waterproof string of LED's.

I first tried the BlinkM but it was not bright enough for my outdoor application and the i2c bus is prone to noise problems over the 100 feet I want to string the lights. A cool thing about all these chips is that they cascade the data and clock from chip to chip keeping the logic levels clean and perky.
8  Forum 2005-2010 (read only) / Interfacing / Re: i2c communication with Led Driver on: May 15, 2008, 04:31:23 pm
There is an I2C library available on the arduino site.

You might want to look at the BlinkM - available from SparkFun. It can easily do just what you want but it would cost you $130-150 dollars for 12.

9  Forum 2005-2010 (read only) / Exhibition / Re: Control Arduino with Universal Remote on: May 26, 2008, 09:32:31 pm
Thanks for the Library!
Pages: [1]