Many many PWMs - General Discussion - Netduino Forums
   
Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Many many PWMs


  • Please log in to reply
19 replies to this topic

#1 Kermit

Kermit

    Advanced Member

  • Members
  • PipPipPip
  • 78 posts
  • LocationCittà di Castello, Italy

Posted 21 April 2012 - 11:09 AM

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.
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

#2 ItsDan

ItsDan

    Advanced Member

  • Members
  • PipPipPip
  • 101 posts

Posted 21 April 2012 - 11:56 AM

PWM IC: http://www.sparkfun.com/products/10136 On a breakout board: http://www.sparkfun.com/products/10615
Follow the adventures of the Box of Crappy Surplus

Total BOCS Traveled Distance: 9708 miles | States Visited: 5
Track the Box

#3 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 21 April 2012 - 11:56 AM

Hi Andrea, You could add a PWM chip to your Netduino's SPI or I2C connection...and then send commands to control its PWM outputs. This is actually one of the use cases for Netduino Go as well...once we have a multi-PWM module for it. You'd be able to plug in modules to add additional PWMs...and then use them from code using the standard PWM object. Chris

#4 Kermit

Kermit

    Advanced Member

  • Members
  • PipPipPip
  • 78 posts
  • LocationCittà di Castello, Italy

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

#5 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 21 April 2012 - 01:47 PM

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.

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.

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 aalmada

aalmada

    Advanced Member

  • Members
  • PipPipPip
  • 44 posts
  • LocationPortugal

Posted 21 April 2012 - 06:51 PM

Pololu Micro Serial Servo Controller (assembled) http://www.pololu.co...log/product/207 Pololu RC Servo Controllers http://www.pololu.co...log/category/12

#7 Kermit

Kermit

    Advanced Member

  • Members
  • PipPipPip
  • 78 posts
  • LocationCittà di Castello, Italy

Posted 21 April 2012 - 08:01 PM

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

#8 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 21 April 2012 - 08:33 PM

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

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 Kermit

Kermit

    Advanced Member

  • Members
  • PipPipPip
  • 78 posts
  • LocationCittà di Castello, Italy

Posted 22 April 2012 - 06:45 AM

...mmmmm... I think I ended my apologies... what I can say is that now I think it's my Google, to be faulty... :lol: Thanks again Andrea

#10 aalmada

aalmada

    Advanced Member

  • Members
  • PipPipPip
  • 44 posts
  • LocationPortugal

Posted 03 May 2012 - 11:14 AM

News from Adafruit... http://player.vimeo.com/video/41452165 EDIT: Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface - PCA9685 http://www.adafruit.com/products/815

#11 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

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?)
Biggest fault of Netduino? It runs by electricity.

#12 BrandonW6

BrandonW6

    New Member

  • Members
  • Pip
  • 8 posts

Posted 05 October 2012 - 01:07 AM

Does anyone know if there are drivers available for that Adafruit 16 channel pwm driver? Any idea how hard it would be to get that working?

#13 carb

carb

    Advanced Member

  • Members
  • PipPipPip
  • 352 posts
  • LocationCrystal River, Florida

Posted 05 October 2012 - 01:34 AM

Brandon,

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 BrandonW6

BrandonW6

    New Member

  • Members
  • Pip
  • 8 posts

Posted 11 October 2012 - 06:15 PM

Thanks for the info Carb, I may try out one of those boards later, I like the idea of driving it direct from USB.

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.

#15 FoxFireX

FoxFireX

    New Member

  • Members
  • Pip
  • 2 posts

Posted 01 December 2012 - 11: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?

#16 Arron Chapman

Arron Chapman

    Advanced Member

  • Members
  • PipPipPip
  • 289 posts
  • LocationOregon, USA

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 FoxFireX

FoxFireX

    New Member

  • Members
  • Pip
  • 2 posts

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.

#18 iced98lx

iced98lx

    Advanced Member

  • Members
  • PipPipPip
  • 134 posts
  • LocationSouth Dakota

Posted 30 December 2012 - 03:42 PM

Thanks for the code Brandon, I'm going to be using the same 16 channel controller for LED control.



#19 iced98lx

iced98lx

    Advanced Member

  • Members
  • PipPipPip
  • 134 posts
  • LocationSouth Dakota

Posted 16 April 2013 - 11:24 PM

Brandon, what value pullup resistors are you using for the adafruit board??



#20 iced98lx

iced98lx

    Advanced Member

  • Members
  • PipPipPip
  • 134 posts
  • LocationSouth Dakota

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

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.