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

74hc595 Shift Register and PWM


  • Please log in to reply
7 replies to this topic

#1 Jardeth56

Jardeth56

    Member

  • Members
  • PipPip
  • 17 posts

Posted 29 October 2014 - 01:52 PM

Hi am new to working with the 74HC595 and I was wondering if someone could point me in the direction of how to send PWM singals via it.

 

I have followed this http://www.oomlout.c...ts/nedx/ncir-05 but the example only shows how to set each pin to high or low any way I can set the pin to a integer?

 

 



#2 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 29 October 2014 - 05:30 PM

You have to toggle the individual shift register outputs on and off periodically. In a trivial example, consider the following pseudocode:
 

while(true)
{                            // Output state
  shiftRegister.Write(0x03); // #0 = on,  #1 = on
  shiftRegister.Write(0x02); // #0 = off, #1 = on
  shiftRegister.Write(0x00); // #0 = off, #1 = off
  shiftRegister.Write(0x00); // #0 = off, #1 = off, 
}

The output #0 (least significant bit) is on for 1/4 of the cycle (loop), which translates to 25% PWM. The output #1 is on for 1/2 cycle -> 50% PWM. The other outputs are zero during the whole cycle -> 0% PWM.

 

The cycle (period) is divided into four parts, which allows only very coarse control (0 - 25 - 50 - 75 - 100%).

 

 

So, to produce PWM signal through shift register, you have to select a specific period, divide it into certain number of parts (finer division means finer PWM, e.g. 256 levels), and then toggle the outputs to produce pulses of a desired width. There are various ways how to implement it, a particularly clever one is called Binary Code Modulation.



#3 Jardeth56

Jardeth56

    Member

  • Members
  • PipPip
  • 17 posts

Posted 29 October 2014 - 05:38 PM

HI CW2 ,

 

Thanks for the info but its a little bit more advanced than I can understand.

 

I have the following code based on the example I provided in my first post.

public class _74HC595
    {
        private OutputPort Data;
        private OutputPort Clock;
        private OutputPort Latch;
        private OutputPort OutputEnablePin;

        public _74HC595(OutputPort data, OutputPort clock, OutputPort latch)
        {
            this.Data = data;
            this.Clock = clock;
            this.Latch = latch;
            //this.OutputEnablePin = outputEnabledPin;
        }



        private int[] bits = { 1, 2, 4, 8, 16, 32, 64, 128 };
        private int[] masks = { 254, 253, 251, 247, 239, 223, 191, 127 };
        int pinState = 0;

        public void ChangePin(int pinId, bool State)
        {
            pinState = pinState & masks[pinId];
            if (State) { pinState = pinState | bits[pinId]; }
            UpdatePin(pinState);
        }


        private void UpdatePin(int value)
        {
            Latch.Write(false);
            for (int i = 0; i < 8; i++)  
            {
                int bit = value & 0x80;  
                value = value << 1;      
                if (bit == 128)
                {
                    Data.Write(true);   
                }
                else
                {
                    Data.Write(false);   
                }

                Clock.Write(true);        
                Thread.Sleep(1);
                Clock.Write(false);
            }
            Latch.Write(true); 
        }
    }

So how would I go about modifying it so that it allows PWM signal?

 

Thanks 



#4 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 31 October 2014 - 03:42 PM

Hi Iain,

 

You might want to consider using a PWM chip e.g. TLC 5940

According to the data sheet, you only need 3 pins to write to it, and it will generate 16 channels of PWM for you.

The nice thing is that you should only have to tell it to set a pulse width once, you will not have to keep your program busy clocking out loads of data into the shift registers to keep the motors running at a constant speed. (If you try to generate PWM from a shift register, any interruption in the sending of the data to the shift register could leave your PWM pin high or low for an unplanned period of time. This would cause the motors to slow down or speed up.)

 

The TLC5490 connections are basically the same as the 74HC595 shift register. Since I know you are trying to reduce the number of pins used, I think you will still want to get the other motor control signals from the shift register, you might consider wiring up the two devices into a chain to keep it at 3 pins, or have the clock and data in parallel, with separate enable lines (4 pins).

 

Paul


  • CW2 likes this

#5 JoopC

JoopC

    Advanced Member

  • Members
  • PipPipPip
  • 148 posts

Posted 01 November 2014 - 07:49 AM

Paul or another, I have a question too,
 
How do I know the state of a Pin of the 74HC595 is high or low, do you have also a solution for that?

a netduino Pin(x).read give a boolean true for high, but now for a 74HC595.

Thank you.

#6 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 01 November 2014 - 08:08 AM

Hi JoopC,

 

Simple answer is that, if all you have is the 74HC595, you can't know the output state of the pins until you have set them.

This can be a real problem at power on / reset.

 

There are some strategies to get the values:

  • You could run a wire back to the Netduino so you can read the state - but that defeats the purpose of using the shift register to get more I/Os!
  • You could add an input shift register (74HC165) to read all the outputs of the 74HC595 and convert them back into a serial message that you can read on the SPI bus. Again this is a bit wasteful unless there are other inputs you needed to sample also, and there is the delay of reading the shift register before you get your answer.
  • Better would be to create a persistent variable that holds the last word you wrote to the shift register, and add some methods to read the word in what ever format you need. Ideally wrap it in a class to look after everything for you once you understand how to write each bit of the code.

 

There is still the power on / reset problem.

One strategy here is to use the enable signal of the 74HC595 to set the outputs to high impedance (e.g. "OFF") at program start, and use pullup or pulldown resistors to set each output to a sensible initial level for your circuit. Once you have written the initial state into the 74HC595, you then enable the outputs of the shift register.

 

Lots to think about, remember its supposed to be fun - Paul



#7 JoopC

JoopC

    Advanced Member

  • Members
  • PipPipPip
  • 148 posts

Posted 03 November 2014 - 06:49 PM

Thanks Paul, clear. I could not find a solution for it and indeed after new power up/reset I lost all the settings. So after all it's better to work with a pcf8574.

#8 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 04 November 2014 - 07:22 PM

Hi Joop,

 

Like the 74HC595, the PCF8574 will not remember the current settings after a power on, and it would not be affected by a reset of the Netduino.

Unlike the 74HC595, when the Netduino comes out of reset, it could poll the PCF8574 to check the current levels on the I/O pins.

 

If I were using one, I would still write a class to control it for me. The class would include a method to read back the most recent settings without having to wait for an I2C operation to complete.

 

Have Fun - Paul






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.