I have been working on a project that will be using python on 2 Raspberry Pi's to control 4 Arduinos and 120 tlc5940's (30 per arduino).
I bought 4 new Arduino Uno R3 smd boards to run the program. However, I had been testing on a Duemilanove before.
The code works exactly as expected when it is ran on my old Duemilanove. Which is what is making me think my issue is hardware related.
When I switched over to the Uno the lights no longer light up consistently, some don't light up at all, and others flicker.
When there are many lights turning on at once it the Uno doesn't work without multiple updateTLCs called. This is not a problem with the Duemilanove.
Things I have tried:
- every baud rate between 9600 and 115200. I found that at 38400 the updateTLC's at least turns on first try.
- playing with dozens of different delay setups in both the python code and the arduino code
- making a link with sudo ln /dev/ttyACM0 /dev/ttyS0 on the raspberry pi
- I have the same troubles when I control the daisy chain directly from the UNO (again not repeatable in the Duemilanove)
- I have tried external power to the Arduinos
- Rechecking all pcb boards, decoupling, buffers, and signal terminators
- Have switched out all 4 Uno's and they all perform identically
- Have tried an even older Diecimila and it works perfectly like the Duemilanove
- checked the config code for the TLC5940 library to be sure that it has the correct number of TLC's set
- gone over the code many times
After checking the software and connections in so many different ways I am wondering if there is a hardware conflict being created by the new USB setup of the UNO. I have ordered some old Due's from ebay (not my favorite choice) especially since this will be installed for a long time, and I would be happier if I could work this out so that I can be using the latest tech. That way I could be more confident about updating it in the future.
I have found issues with uploading to the Uno and getting the Raspberry Pi to communicate with the Uno, neither of these have been an issue for me. I can't find anything directly referring to my problem, any advice or direction would be greatly appreciated.
Below is the Arduino Code
// 2013-06-15
/*
Basic Pin setup:
------------ ---u---- Cable Pin Out
ARDUINO 13|-> SCLK (pin 25) W OUT1 |1 28| OUT channel 0 NC |10 9| Blank
12| OUT2 |2 27|-> GND (VPRG) SIN |8 7| SCLCK
11|-> SIN (pin 26) B OUT3 |3 26|-> SIN (pin 11) GND |6 5| GND
10|-> BLANK (pin 23) Y OUT4 |4 25|-> SCLK (pin 13) XLAT |4 3| GSCLK
9|-> XLAT (pin 24) O . |5 24|-> XLAT (pin 9) GND |2 1| VCC (12V)
8| . |6 23|-> BLANK (pin 10)
7| . |7 22|-> GND
6| . |8 21|-> VCC (+5V)
5| . |9 20|-> 10K Resistor -> GND
4| . |10 19|-> +5V (DCPRG)
3|-> GSCLK (pin 18) G . |11 18|-> GSCLK (pin 3)
2| . |12 17|-> SOUT
1| . |13 16|-> XERR
0| OUT14|14 15| OUT channel 15
------------ --------
- Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
(cathode) in OUT(0-15).
- +5V from Arduino -> TLC pin 21 and 19 (VCC and DCPRG)
- GND from Arduino -> TLC pin 22 and 27 (GND and VPRG)
- digital 3 -> TLC pin 18 (GSCLK)
- digital 9 -> TLC pin 24 (XLAT)
- digital 10 -> TLC pin 23 (BLANK)
- digital 11 -> TLC pin 26 (SIN)
- digital 13 -> TLC pin 25 (SCLK)
- The 2K resistor between TLC pin 20 and GND will let ~20mA through each
LED. To be precise, it's I = 39.06 / R (in ohms). This doesn't depend
on the LED driving voltage.
- (Optional): put a pull-up resistor (~10k) between +5V and BLANK on the first board so that
all the LEDs will turn off when the Arduino is reset.
If you are daisy-chaining more than one TLC, connect the SOUT of the first
TLC to the SIN of the next. All the other pins should just be connected
together:
BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
XLAT on Arduino -> XLAT of TLC1 -> XLAT of TLC2 -> ...
The one exception is that each TLC needs it's own resistor between pin 20
and GND.
This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
Do not use analogWrite(...) on these pins.
*/
// for my setup:
// latch green
// clock yellow
// gclock yellow/black
// data blue
// blank blue/black
//#include "Tlc5940.h"
//#include <tlc_servos.h>
//#include <tlc_animations.h>
//#include <tlc_progmem_utils.h>
#include <tlc_config.h>
#include <Tlc5940.h>
//#include <tlc_shifts.h>
//#include <tlc_fades.h>
int brightness = 4095; // brightness level for LEDs. 0 - 4095
const int numNames = 16*NUM_TLCS;
int names[numNames];
unsigned long serialdata;
int inbyte;
String indata;
void setup()
{
/* Call Tlc.init() to setup the tlc.
You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
clearNames();
Tlc.init(1000);
delay(1000);
Serial.begin(9600);
Tlc.clear();
while(Tlc.update());
delay(50);
}
/* NUM_TLCS is defined in "tlc_config.h" in the
library folder. After editing tlc_config.h for your setup, delete the
Tlc5940.o file to save the changes. */
void loop()
{
indata = ""; // empty buffer for serial data
if(Serial.available()>0) { //check to see if data is available
delay(5); // wait for data to be completely sent
readData(); // read in string of data until ; is encountered
switch(indata[0]) {
case 'u': // 'u' means update tlc
while(Tlc.update());
break;
case 'c': // 'c' means clear tlc
Tlc.clear();
break;
case 'l': // 'l' means turn on the numbered list of leds which follows. l12,3000,;
parseNames();
int led;
led = names[0];
int bright;
bright = names[1];
if (bright > brightness){
bright = 4095;
}
if (bright < 0) {
bright = 0;
}
turnOn(led, bright);
break;
case 'a': // 'a' means turn all on. command to send is a####; where #### is brightness level
int beginIdx = 1;
int idx = indata.indexOf(";");
String brightString = indata.substring(beginIdx, idx);
char brightArray[16];
brightString.toCharArray(brightArray,16);
bright = atoi(brightArray);
Tlc.setAll(bright);
break;
}
}
}
void readData() { // read data from serial until ; is encountered
while(Serial.available()>0) { // while data is available
char inchar = Serial.read(); // get a character
delay(5);
if (inchar == ';') { // ; indicates end of command
break;
}
else{
indata += inchar; // build string.
}
}
}
//
// gets light & brightness data from a command of the form
// l15,200,;
// that's a lowercase L followed by the led number a comma the brightness a comma and a semicolon
void parseNames() { // parse serial data from string to int array
clearNames();
int name=0;
int beginIdx = 1;
int idx = indata.indexOf(",");
char portBuf[16];
while (idx != -1) {
String port = indata.substring(beginIdx, idx);
port.toCharArray(portBuf, 16);
names[name++] = atoi(portBuf);
beginIdx = idx+1;
idx = indata.indexOf(",",beginIdx);
}
}
void turnOn(int led, int bright) {
if (bright > 4095){bright=4095;}
if (bright < 0){bright=0;}
Tlc.set(led,bright); // turn on led at port 'led' with brightness 'bright'
delay(1);
}
void clearNames() {
for (int name = 0; name < numNames; name++) {
names[name] = 0;
}
}