May 18, 2024, 05:36:21 AM

News:

Be sure to checkout our Vixen interfaces in the Library forum -- if you want PC automation at near zero cost, EFX-TEK and Vixen is a great combination of tools.


Look, Mom! Two Props at Once!

Started by JonnyMac, April 10, 2012, 12:35:16 PM

Previous topic - Next topic

JonnyMac

April 10, 2012, 12:35:16 PM Last Edit: April 10, 2012, 02:58:35 PM by JonnyMac
The HC-8+ uses the P8X32A "Propeller" microcontroller -- which actually has eight 32-bit processing cores (called cogs) on one slab of silicon.  This gives the Propeller a lot of horsepower and is how we were able to create the AP-16+ without having to use an external audio decoding chip.

What's neat is that the Spin language allows us to launch multiple cogs in the same program file -- with this process we can in fact have control multiple props from the same board.  And in the HC-8+ we're not jumping through programming hoops like on the Prop-1, Prop-2, and Prop-SX.

Let's start with a simple one.  If you've seen our trade show booth you know that we have candles and a "mood skull" (the latter is a crystal skull that slowly and smoothly changes colors using RGB LEDs).  For fun, I bundled those two processes into a single HC-8 file.

Here's the working guts.  What you can see is that the overall program launches the dimmer object so we can control output lvels on the eight channels.  The main method launches the drugar method into it's own cog so that it can run indipently.  The rgb_mixer cog runs the RGB leds and the main cog continues running the others as candle wicks.  I added a fade up on the candles just to show you how it can be done.

pub main | ch, t

  outa[OUT7..OUT0] := %0000_0000                                ' clear outputs
  dira[OUT7..OUT0] := %1111_1111                                ' output mode                                 
  low(OUT_EN)                                                   ' enable 74x245

  ' setup randomizer
  ' -- use hardware to seed advanced pseudo-random object
  ' -- excellent random without extra cog (loaded and then released)
                                                     
  rr.start                                                     
  prng.seed(rr.random, rr.random, rr.random, rr.random, rr.random)
  rr.stop
                                                       
  leds.start(8, OUT0)                                           ' start LED dimmer

  ' launch rgb mixer code in separate cog
  ' -- will run independly of candles code
  ' -- both cogs can share system objects
 
  cognew(rgb_mixer, @stack0)   


  ' run candles in this cog

  repeat ch from WICK1 to WICK5                                 ' seed the wicks
    target[ch] := prng.random // 55 + 201                       ' set 1st target

  brightness := 0                                               ' start off

  t := cnt                                                      ' synchronize timer
  repeat                                                        ' run forever
    repeat ch from WICK1 to WICK5                               ' loop through wicks
      if (level[ch] == target[ch])                              ' at target?
        target[ch] := prng.random // 55 + 201                   '  yes, set new one
      elseif (level[ch] < target[ch])                           ' below target?
        level[ch] := ++level[ch] <# 255                         '  increase and limit
      else                                                      ' above target
        level[ch] := --level[ch] #> 0                           '  decrease and limit

      leds.set(ch, level[ch] * brightness / 255)                ' set channel
      brightness := ++brightness <# 255                         ' increase wicks level

      waitcnt(t += (2_500 * US_001))                            ' wait 2.5ms 
   

con

  { =================== }
  {                     }
  {  R G B   M I X E R  }
  {                     }
  { =================== }


pri rgb_mixer | t, lottery, ch                                  ' start with cognew

'' RGB LED mixer
'' -- runs "mood skull" style RGB lighting mixer
'' -- randomly selects color channel, fades it up or down

  t := cnt                                                      ' sync timer
  repeat
    lottery := prng.random                                      ' randomize
    ch := (||lottery // 3) + RGB_R                              ' select channel
    if (leds.read(ch) == 0)                                     ' check level
      repeat 255
        leds.inc(ch)                                            ' increase ch level
        waitcnt(t += (MS_001 << 4))                             ' wait 16ms
    else
      repeat 255
        leds.dec(ch)                                            ' decrease ch level
        waitcnt(t += (MS_001 << 4))                             ' wait 16ms   



Of course, you'll need the whole package -- it's attached (with all the objects you need to run this).
Jon McPhalen
EFX-TEK Hollywood Office

JonnyMac

April 10, 2012, 03:06:26 PM #1 Last Edit: April 10, 2012, 03:09:01 PM by JonnyMac
Was watching the RGB LED for a while and didn't like that sometimes it was off -- the nature of random.  Here's a small update that checks for before a ramp-down of one channel that at least one of the others is on.   It's a little tricky in the way it uses nested repeat loops.  Spend some time with it and it will make sense.

pri rgb_mixer | t, lottery, ch                                  ' start with cognew

'' RGB LED mixer
'' -- runs "mood skull" style RGB lighting mixer
'' -- randomly selects color channel, fades it up or down

  t := cnt                                                      ' sync timer
  repeat
    repeat
      lottery := prng.random                                    ' randomize
      ch := (||lottery // 3) + RGB_R                            ' select channel
      if (leds.read(ch) == 255)                                 ' if ramping down
       
        ' make sure at least one other channel is on
     
        case ch
          0: if (leds.read(1) + leds.read(2) == 0)
               quit
          1: if (leds.read(0) + leds.read(2) == 0)
               quit
          2: if (leds.read(0) + leds.read(1) == 0)
               quit                                                                                 
                                                                 
      if (leds.read(ch) == 0)                                   ' check level
        repeat 255                                               
          leds.inc(ch)                                          ' increase ch level
          waitcnt(t += (MS_001 << 4))                           ' wait 16ms
      else                                                       
        repeat 255                                               
          leds.dec(ch)                                          ' decrease ch level
          waitcnt(t += (MS_001 << 4))                           ' wait 16ms
Jon McPhalen
EFX-TEK Hollywood Office