Many many PWMs
#1
Posted 21 April 2012 - 11:09 AM
Yes, the first straight answer could be to buy more Netduinos, but it's not only a cost problem: then I'd have to sync all together, that would be another big problem!
What I'm thinking about, is there some solution where I first select an 'address' (to be considered in a wider sense...), and then I set a duty cycle? The 'subcircuit' (or something like that) should retain that value, be self-powered, and going on supplying the exact pulse until maybe I re-select the same 'address', and put out a new value.
The first idea coming to my mind is to use many shift register chained in SPI, where, using the output pins of each shift register, put out a 'value' to feed to something else to be used as a PWM source (and obviously I don't know how to create such a thing...).
I googled everywhere, but I couldn't find any good start, so I'm really at zero! :-(
Is there anyone pointing me to a good direction?
Thanks in advance
Andrea
- Arron Chapman likes this
#2
Posted 21 April 2012 - 11:56 AM
Total BOCS Traveled Distance: 9708 miles | States Visited: 5
Track the Box
#3
Posted 21 April 2012 - 11:56 AM
#4
Posted 21 April 2012 - 12:26 PM
PWM IC:
http://www.sparkfun.com/products/10136
On a breakout board:
http://www.sparkfun.com/products/10615
...ehm... I don't know how to tell it in English, but right now I have a big big red face... :-(
Andrea
- devnightmare likes this
#5
Posted 21 April 2012 - 01:47 PM
There is a PWM example using the TLC5940 chip in the project showcase here. The demonstration shows 16 PWM signals from the Netduino but there is no reason it cannot be expanded. In fact the class allows for more.Since my other thread is getting long (Train models), I start here a new thread for a subproblem: how to drive, for example, 20 PWM signals from a single Netduino.
Regards,
Mark
To be or not to be = 0xFF
Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life
Follow @nevynuk on Twitter
#6
Posted 21 April 2012 - 06:51 PM
#7
Posted 21 April 2012 - 08:01 PM
#8
Posted 21 April 2012 - 08:33 PM
Andrea,I thank you all for your input, but I'm living in Italy, and I'm seeing that I cannot find all over Europe someone who sells the shields you talked about in the previous messages: I can barely find the (naked) TLC5940 chip, I think I'll have to build the circuits myself... :-(
Andrea
There are plenty of places in Europe selling Sparkfun products. I'm in the UK and I can get them from Proto-Pic and I believe there are others in the UK. You can find a full list of distributors on Sparkfun's distributor page.
Hope this helps,
Mark
To be or not to be = 0xFF
Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life
Follow @nevynuk on Twitter
#9
Posted 22 April 2012 - 06:45 AM
#10
Posted 03 May 2012 - 11:14 AM
#11
Posted 03 May 2012 - 11:35 AM
News from Adafruit...
http://player.vimeo.com/video/41452165
I'm much more impressed by the Limor's alternative-look, other than a bunch or little spiders moving on the desk. (The servos look like the fresh fish at the market...do you know?)
#12
Posted 05 October 2012 - 01:07 AM
#13
Posted 05 October 2012 - 01:34 AM
I do not know about the Adafruit version but Pololu does have a servo control in both a USB and serial version.
I have a 6 and 18 servo model but so far have only tried with the usb cable. Not from a netduino. Stefan has drivers for the serial only model, but the usb version does take serial inputs also.
Mini Maestro Servo Control
Stefan's drivers are in his .Net Microframework Toolbox.
Chuck
#14
Posted 11 October 2012 - 06:15 PM
But in any case, I had already ordered the Adafruit 16 channel 12 bit Pwm driver. I translated the arduino driver files into c# and found it works great using i2c to communicate to the board. Here is the driver code for anyone who needs it:
/* * Adafruit 16 channel 12 bit PWM Servo Driver NETMF * Code Translated by Brandon Watt Oct 2012 * * This board use I2C to communicate, 2 pins are required to * interface. For Netduino/Arduino Uno, thats SCL -> Analog 5, SDA -> Analog 4 * * Brandon Watt: Inital release (1.0) Translated arduino code into c# * Based on driver files found at "https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library" * */ using System; using Microsoft.SPOT; using System.Threading; using Toolbox.NETMF.Hardware; namespace Adafruit_16channel { class Adafruit_PWMServoDriver { private MultiI2C _Device; private const byte PCS9685_SUBADR1 = 0x2; private const byte PCA9685_SUBADR2 = 0x3; private const byte PCA9685_SUBADR3 = 0x4; private const byte PCA9685_MODE1 = 0x0; private const byte PCA9685_PRESCALE = 0xFE; private const byte LED0_ON_L = 0x6; private const byte LED0_ON_H = 0x7; private const byte LED0_OFF_L = 0x8; private const byte LED0_OFF_H = 0x9; private const byte ALLLED_ON_L = 0xFA; private const byte ALLLED_ON_H = 0xFB; private const byte ALLLED_OFF_L = 0xFC; private const byte ALLLED_OFF_H = 0xFD; private byte _i2caddr; public Adafruit_PWMServoDriver(byte addr = 0x40, int ClockRateKhz = 200) { _i2caddr = addr; this._Device = new MultiI2C(_i2caddr, ClockRateKhz); } public void Begin() { Reset(); } public void Reset() { write8(PCA9685_MODE1, 0x0); } public void setPWMFreq(float freq) { float prescaleval = 25000000; prescaleval /= 4096; prescaleval /= freq; prescaleval -= 1; // Debug.Print("Estimated pre-scale: " + prescaleval); byte prescale = (byte)System.Math.Floor(prescaleval + 0.5); // Debug.Print("Final Pre-scale: " + prescale); byte oldmode = read8(PCA9685_MODE1); byte newmode = (byte)((oldmode & 0x7F) | 0x10); // sleep write8(PCA9685_MODE1, newmode); // go to sleep write8(PCA9685_PRESCALE, prescale); // set the prescaler write8(PCA9685_MODE1, oldmode); Thread.Sleep(5); write8(PCA9685_MODE1, (byte)(oldmode | 0x80)); } public void setPWM(byte num, UInt16 on, UInt16 off) { write8((byte)(LED0_ON_L + 4 * num), (byte)on); write8((byte)(LED0_ON_H + 4 * num), (byte)(on >> 8)); write8((byte)(LED0_OFF_L + 4 * num), (byte)off); write8((byte)(LED0_OFF_H + 4 * num), (byte)(off >> 8)); } private byte read8(byte addr) { byte[] ReadBuffer = new byte[1]; this._Device.WriteRead(new byte[] { addr }, ReadBuffer); return ReadBuffer[0]; } private void write8(byte addr, byte d) { this._Device.Write(new byte[] { addr, d }); } } }
To use this driver you must have the .Net MF toolkit as it uses the MultiI2c Device class
To setup the driver for your servo first call on the instance:
pwm.setPWMFreq(50); // This sets the frequency pre-scale to 50hz
To set the servo or PWM values you call:
pwm.setPWM(0, 0, PulseLength); // (servo number 0-15, start of pulse, end of pulse)
Because of the prescale, the values for pulse length are lower then you expect. Since they correlate to percentage of entire on/off cycle, using 12 bits gives values between 0 to 4096 so to control a standard servo, the range runs from about 150 to 600. Or you can use the following function that does the calculation to map the values for you.
public static void setServoPulse(byte n, double pulse) { double pulselength; pulselength = 20000; // 1,000,000 us per second pulselength /= 50; // 50 Hz pulselength /= 4096; // 12 bits of resolution pulse *= 1000; pulse /= pulselength; Debug.Print("Pulse " + pulse); pwm.setPWM(n, 0, (ushort)pulse); }
Figured someone else may want to use this board, and this will save you some time.
- iced98lx likes this
#15
Posted 01 December 2012 - 11:04 PM
#16
Posted 02 December 2012 - 05:04 PM
I've been working on a project where I need to do independent control of quite a few (~150) LED channels. Many of them are RGB, some not. Anyway. I've been working on it using TLC5941s to this point, and thought things were going well, but I'm starting to hit some roadblocks.
While on the breadboard, I was able to daisy chain two chips with no problem, but knowing the Netduino has a maximum current through its 3.3V out pin, I planned the standalone PCBs to have independent power supplies. I have one board that has a single TLC chip and the timing logic, and three boards with three additional chips, each with an independent power supply connection. The first chip works as expected, but the daisy chain boards start showing unexpected behavior; much of the time, the shift register values flow to each chip and output as expected, but far too often the resulting LED states are incorrect, sometimes extras on, sometimes off.
My best guess at this point, from some of the reading I've done, is that I may need to add decoupling capacitors, but my first attempt hasn't solved the problem. So, in search of answers, I was looking around and found this thread. The main question I find myself looking at now is this: Am I better off trying to continue troubleshooting with the TLC5941s, and eventually probably ordering new PCBs and new chips, or would I be better served to switch to another solution like the Adafruit boards mentioned here? If I switch, will it be compatible with the LEDs I already have set up? (Don't remember if they were common anode or common cathode, just that it was TLC5941 compatible.)
If I go for this, I'll have to order a set of ten boards, which it looks like would be supported, but I'd really hate to sink $150 into this solution only to fail again. Anyone with experience on either/both approaches who could provide some insight?
Do all of your circuits share a common GND? They Should.
When you talk EE use small words, I'm just a Software Developer
My Blog/Site and Everything Else
If my post helped you please consider pressing the "Like This" button in the bottom right-hand corner.
Oh my. So many things, so little money!!
#17
Posted 02 December 2012 - 05:30 PM
Do all of your circuits share a common GND? They Should.
Yeah, all grounds tied together. My guess has been that there is some sort of voltage shift happening somewhere along the line that's either corrupting the serial line between the chips, or is causing its reference voltage to determine high/low on that line is getting shifted. Seems possible with the different LEDs going on and off, but at the same time I'd expect the TLCs to already be able to handle that.
#19
Posted 16 April 2013 - 11:24 PM
Brandon, what value pullup resistors are you using for the adafruit board??
#20
Posted 18 April 2013 - 02:08 AM
So I modified this driver to use NooM's multi-i2c driver vs the toolbox after I couldn't get the toolbox and the original to work. Nothing at all wrong with the driver the way I see it, everything but the functions that were being called were left the same. You'll notice that I changed the write8 and read8 method vs updating it to use NooM's functions. I'll likely consolidate the multii2c and pwm driver at some point.
using System;using System.Threading;using Microsoft.SPOT.Hardware;using Tools; //NooM's multi i2c Driver// This works on the N+2's SD SC pins NOT analog 4&5 namespace Testingi2c{ class Adafruit_PWMServoDriver { private MultiI2C _Device; private const byte PCS9685_SUBADR1 = 0x2; private const byte PCA9685_SUBADR2 = 0x3; private const byte PCA9685_SUBADR3 = 0x4; private const byte PCA9685_MODE1 = 0x0; private const byte PCA9685_PRESCALE = 0xFE; private const byte LED0_ON_L = 0x6; private const byte LED0_ON_H = 0x7; private const byte LED0_OFF_L = 0x8; private const byte LED0_OFF_H = 0x9; private const byte ALLLED_ON_L = 0xFA; private const byte ALLLED_ON_H = 0xFB; private const byte ALLLED_OFF_L = 0xFC; private const byte ALLLED_OFF_H = 0xFD; private byte _i2caddr; public Adafruit_PWMServoDriver(byte addr = 0x40, int ClockRateKhz = 200) { _i2caddr = addr; this._Device = new MultiI2C(new I2CDevice.Configuration(0x40, 200)); } public void Begin() { Reset(); } public void Reset() { write8(PCA9685_MODE1, 0x0); } public void setPWMFreq(float freq) { float prescaleval = 25000000; prescaleval /= 4096; prescaleval /= freq; prescaleval -= 1; // Debug.Print("Estimated pre-scale: " + prescaleval); byte prescale = (byte)System.Math.Floor(prescaleval + 0.5); // Debug.Print("Final Pre-scale: " + prescale); byte oldmode = read8(PCA9685_MODE1); byte newmode = (byte)((oldmode & 0x7F) | 0x10); // sleep write8(PCA9685_MODE1, newmode); // go to sleep write8(PCA9685_PRESCALE, prescale); // set the prescaler write8(PCA9685_MODE1, oldmode); Thread.Sleep(5); write8(PCA9685_MODE1, (byte)(oldmode | 0x80)); } public void setPWM(byte num, UInt16 on, UInt16 off) { write8((byte)(LED0_ON_L + 4 * num), (byte)on); write8((byte)(LED0_ON_H + 4 * num), (byte)(on >> 8)); write8((byte)(LED0_OFF_L + 4 * num), (byte)off); write8((byte)(LED0_OFF_H + 4 * num), (byte)(off >> 8)); } private byte read8(byte addr) { byte[] ReadBuffer = new byte[1]; this._Device.ReadRegister(addr, ReadBuffer); return ReadBuffer[0]; } private void write8(byte addr, byte d) { this._Device.WriteRegister(addr, d); } }}
Then, since I'm not doing servo's but rather LED control I thought I'd offer a piece of code that worked to set brightness on the PWM pin:
var Light1 = new Adafruit_PWMServoDriver(0x40, 200); // new object to control a board passing in the address and speedLight1.Reset(); // if you don't do this it does funny things on restart.Light1.setPWMFreq(500); // set the freq the drivers I'm using support 100->1000mhz so does the board.Light1.setPWM(0, 1000, 4090); // set the first PWM control to about 3/4 brightness
That worked for me. I'm still playing with advanced options (this chip has great options with it!)
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users