Shop OBEX P1 Docs P2 Docs Learn Events
Propeller newbie question on using HC595 shift register with Spin; Ardunio code works, Spin does not — Parallax Forums

Propeller newbie question on using HC595 shift register with Spin; Ardunio code works, Spin does not

I am new to the Propeller and Spin.
I have question on a simple setup with 2 chained HC595 shift registers controlling 16 LEDs.
I am trying to duplicate the behavior of some Arduino code on the Propeller; the Arduino code works just fine on my hardware setup, but the Spin version does not. The Spin works ok for the lower order 8 bits but not for the upper 8 bits of the 16 bits going out.
When I put out $0002, the first 595 shows the second bit on, all others off. Good.
When I put out $0200, the first 595 shows all LEDs off, and the second 595 shows the first and second bits on, instead of just the first bit.
The code has a commented out test counter as well, which shows the problem.
My question is what is missing/wrong in my Spin code?
(note: some code derived from Chris Savage and I am sure it is not a problem from his code).

I have attached the Arduino code which works and the Spin code which does not.
Thanks for any help.

Comments

  • AntediluvianAntediluvian Posts: 87
    edited 2018-03-27 19:03
    Hello,

    I have been struggling with whether to put everything back up on my website since I am no longer working with this stuff anymore. However, I will look at my archives and see what I can find.

    Edit: See next post where I found one of my '595 tutorials in SPIN. Uses only one shift register, but could easily be modified for up to 4 with only 2 small changes.
  • These are screenshots from my old website. I also included the timing diagram, schematic and SPIN code.
  • Thanks for the response. I saw your code on one of my Parallax/Google searches, and I think my code conforms to what your did. But I can't get the high order bits sent out to two chained 595s to show correctly. The lower 8 bits (first 595) show correctly but the second always has more bits going out parallel that the serial data sent in.
    I also tried the shift register code I found on OBEX ("Shift in out demo", 74HC595_Regular.spin) and could not get those to show the 8 MSB correctly.
    So I must be doing something wrong, and would suspect my hardware setup. But like I said it shows just fine with the simple Arduino code.
  • Do you have nice short connections from the prop to the shift registers?
    How about a really good ground?
    Could you post a photo?
  • kwinnkwinn Posts: 8,697
    Why not just rotate the data so the high and low 8 bits are in the correct position before calling writeHC595? Faster and simpler than dividing and modulus operations.
  • kwinnkwinn Posts: 8,697
    PS, the state (high/low) of the pins are not set initially so you may be getting an extra clock pulse before you get to the "dataOut16Bit" subroutine.
  • AntediluvianAntediluvian Posts: 87
    edited 2018-03-27 21:30
    I don't have any Parallax hardware set up to test this, but in the code I wrote you should be able to do 16 bits using the following modified PRI method. This, of course, assumes you have the wiring of the daisy-chained '595's correct.
    PRI writeHC595(bits)
    
      bits <-= 16                                                                   ' Move Bits To MSB
    
      repeat 16                                                                     ' 16 Bits
        outa[HC595_DI] := bits <-= 1                                                ' Rotate Bits And Output LSB
        outa[HC595_CLK] := 1                                                        ' Clock The HC595
        outa[HC595_CLK] := 0
    
      outa[HC595_LATCH] := 1                                                        ' Latch The Outputs
      outa[HC595_LATCH] := 0
                 
    
    :nerd:
  • Do you have nice short connections from the prop to the shift registers?
    How about a really good ground?
    Could you post a photo?

    Short connections and well grounded I beleive. This is the exact same setup/wires I used with the Arduino.
    Photo attached.
    5262 x 1658 - 2M
  • I don't have an HC595 to test but something caught my attention: It appears that your 'pause' is only a micro second plus the overhead of a method call.
    PRI Pause(ms)
      waitcnt(clkfreq / 1000 * ms + cnt) ' Convert To mS THIS ACTUALLY EQUALS A MICRO SECOND
    

    Please try this and see if it helps.
    PUB Main | i, highBits, lowBits
      ' set pins to output
      dira[SR_CLOCK]~~
      dira[SR_LATCH]~~
      dira[SR_DATA]~~
      
      pauseMS := 1000
      ' test 
      repeat
        dataOut16Bit($0001)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)     
        dataOut16Bit($0002)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)
        dataOut16Bit($0100)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)
        dataOut16Bit($0200)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)
    
  • kwinn wrote: »
    Why not just rotate the data so the high and low 8 bits are in the correct position before calling writeHC595? Faster and simpler than dividing and modulus operations.

    Thanks for the post. I tried both ways and got the same result.

    'high8Bits := data / 256
    'low8Bits := data // 256 'modulus
    high8Bits := data >> 8
    low8Bits := data & $00FF
  • pclem wrote: »
    Do you have nice short connections from the prop to the shift registers?
    How about a really good ground?
    Could you post a photo?

    Short connections and well grounded I beleive. This is the exact same setup/wires I used with the Arduino.
    Photo attached.

    The photo attached shows the result of an output of: dataOut16Bit($0100), LEDs 1,2 on the second shift register being on instead of just LED 1.
    An output of dataOut16Bit($0200) results in LEDs 3,4 being on. That may be a clue, but once again the exact same hardware/conneciton setup on the Arduino works correctly.

  • tomcrawfordtomcrawford Posts: 1,126
    edited 2018-03-27 22:02
    If you have a few 104 caps you might try some bypassing on the 595 board. (Yes, I know it works perfectly with *d**no).

    Edit: Are you using a 5 volt Aduino?
  • If you have a few 104 caps you might try some bypassing on the 595 board. (Yes, I know it works perfectly with *d**no).

    Edit: Are you using a 5 volt Aduino?

    Yes. When the board is hooked to the Arduino, it is plugged into the 5 volts. Same with the Propeller.
  • lardom wrote: »
    I don't have an HC595 to test but something caught my attention: It appears that your 'pause' is only a micro second plus the overhead of a method call.
    PRI Pause(ms)
      waitcnt(clkfreq / 1000 * ms + cnt) ' Convert To mS THIS ACTUALLY EQUALS A MICRO SECOND
    

    Please try this and see if it helps.
    PUB Main | i, highBits, lowBits
      ' set pins to output
      dira[SR_CLOCK]~~
      dira[SR_LATCH]~~
      dira[SR_DATA]~~
      
      pauseMS := 1000
      ' test 
      repeat
        dataOut16Bit($0001)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)     
        dataOut16Bit($0002)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)
        dataOut16Bit($0100)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)
        dataOut16Bit($0200)
     '   pause(pauseMS)
        waitcnt(clkfreq / 1000 + cnt)
    

    Hi Larry,
    Not sure I understand. The LED blink pause, is pausing correctly for 1 sec.
    If pauseMS is 1000, then my Pause function would work out to be:

    waitcnt(clkfreq / 1000 * 1000 + cnt)

    And I seems to pause as intended.
    Am I missing something that your are saying?


  • @pclem, I guess I should have double checked on the PST.
    clkfreq / 1000 * 1000 = 1 second
    A one second pause simplifies to
    waitcnt(clkfreq + cnt)
    
  • Thanks to everyone for the help.
    I swapped out the 595 chips and pulled the jumper wires on the breadboard and re-pushed them in. I did not find any thing that was wired up incorrectly, but it now works on the Propeller and oddly it still works as it did before on the Arduino. Perhaps a glitch in the breadboard? Don't know.
    It is a bit of an unsolved mystery, but I won't argue with it. It now works as it should.
    Thanks again.
  • How does this code know you are talking about the high order bit of bits?
    PRI writeHC595(bits)
    
      bits <-= 24                      ' Move Bits To MSB
      repeat 8                         ' 8 Bits
        outa[SR_DATA] := bits <-= 1    ' Rotate Bits And Output
        outa[SR_CLOCK] := 1            ' Clock The HC595
        outa[SR_CLOCK] := 0
    

    I refer particularly to outa[SR_DATA] := bits <-=1. I get it that it left shifts after the := part, but I don't see that the data bit chosen is necessarily bit 31.
  • I wrote a library that will allow you to shift 1, 2, 3, or 4 bytes to a chain of '595s. I have even used this in commercial projects. Since you're not using the enable pin specify -1 for that parameter.
  • How does this code know you are talking about the high order bit of bits? I get it that it left shifts after the := part, but I don't see that the data bit chosen is necessarily bit 31.

    When the 'rotate left 1 bit' is completed, the MSB will now be at the LSB. Since the assignment is a bit value, the LSB appears at the I/O pin connected to DI on the 74HC595. The reason I do it this way is because we're shifting the bits from the MSB first, so this accomplishes that task in the right order.

    I don't see the need for all those delays in the previous examples. I empirically tested the speeds and the SPIN language can't exceed the speed of a 74HC595. The delays are just wasted code space and complexity, not to mention, delays...something you typically want to avoid.

  • How does this code know you are talking about the high order bit of bits?
    Whenever you have code like this:
      outa[PINX] := someValue
    
    ...only the LSB of someValue is used. In the code you reference...
      outa[SR_DATA] := bits <-= 1
    
    ...the value of bits is rotated left ( <-= ) which places what was in bit31 (MSB) into bit0 (LSB). This value is then placed on the data line. This mechanism is MSBFIRST which is why my driver flips the bits ( ><= ) if LSBFIRST mode is specified
  • In regards to whether you need to slow down anything I would say absolutely not, especially since Spin is relatively slow anyway.

    When I talk to shift registers in Tachyon Forth I can setup the pins with a single instruction and then all I need to do to write 16-bits over SPI is use the SPIWR16 instruction which takes 4.8us to execute. I recently interfaced to 8 shift registers connected to bar-graph LEDs so I simply used two SPIWR32 instructions to write all 64-bits from a buffer in under 20us.

    So there is no need to insert any kind of delays in Spin, that's for sure.
  • Mark_TMark_T Posts: 1,981
    edited 2018-03-28 14:02
    Its mandatory to decouple all logic chips - 100nF ceramic at the pins is normal. If you are driving LEDs like this add 10uF or more of electrolytic.

    The symptoms of no decoupling is exactly this kind of random behaviour, and its very common driving high current loads like LEDs (yes LEDs are high current loads for a logic signal).

    Never use a logic IC without at least one 100nF ceramic cap for supply decoupling, unless you want things to go wrong at random!

    The change from 5V to 3.3V clearly caused the behaviour to change between Arduino and Prop, again exactly the sort
    of thing I'd expect without decoupling.
  • In regards to whether you need to slow down anything I would say absolutely not, especially since Spin is relatively slow anyway. So there is no need to insert any kind of delays in Spin, that's for sure.

    Peter, agreed! As of when I wrote that code every example SPIN object I saw had delays between each bit, between the latch pin toggles and between bytes going out. None were ever necessary. I haven't worked with this in over a year, but IIRC even PASM wouldn't require delays for the bits shifting when running at 80 MHz.
  • JonnyMacJonnyMac Posts: 9,104
    edited 2018-03-28 19:24
    even PASM wouldn't require delays for the bits shifting when running at 80 MHz.
    I can vouch for that; I'm working on a project now that uses a PASM driver to run low-frequency PWM through 16 outputs using two 595s -- there are no delays in the code.
  • Thanks for confirmation Jon. Just looking at the datasheet would seem to support that (at least with the HC part), but I remember in SPIN watching the data on the Logic Analyzer just for speed testing purposes. PASM would definitely be the way to go.
  • >>This mechanism is MSBFIRST which is why my driver flips the bits ( ><= ) if LSBFIRST mode is specified[/quote]

    To JonnyMac: Thanks for the jm_595 code. I will learn from it.
Sign In or Register to comment.