Shop OBEX P1 Docs P2 Docs Learn Events
Generate non-uniform pulse — Parallax Forums

Generate non-uniform pulse

engineearengineear Posts: 4
edited 2014-09-21 07:37 in Propeller 1
I am looking to generate two non-uniform pulse on two output lines to cycle two individual components. The cycle time is on the order of 5 milliseconds. I have the sequence in a spreadsheet with the on/offs for each component at each 5ms time step. Is there an easy way to have the propeller take the sequence from a spreadsheet or do i have to create a line for every timestep?

Comments

  • HarpritHarprit Posts: 539
    edited 2014-09-05 09:02
    You should be able to copy a fixed, comma limited data group from Excel and paste it into your SPIN program with ease
    Doing it in real time with ever changing data might be a bit more difficult.
    H
  • jmgjmg Posts: 15,173
    edited 2014-09-05 15:46
    engineear wrote: »
    I am looking to generate two non-uniform pulse on two output lines to cycle two individual components. The cycle time is on the order of 5 milliseconds. I have the sequence in a spreadsheet with the on/offs for each component at each 5ms time step. Is there an easy way to have the propeller take the sequence from a spreadsheet or do i have to create a line for every timestep?

    How big is the spreadsheet ?
    If you only need this once, a copy/paste/edit can work, if you want to create many 'build variants' then I've used programs like FreeBasic to do simple file table conversions.

    If you want this more 'live', FreeBasic can also do File to Serial Data quite easily.

    [www.freebasic.net &
    fbide.freebasic.net & this Debug is quite good
    http://www.freebasic.net/forum/viewtopic.php?f=8&t=13935

    ]
  • MJBMJB Posts: 1,235
    edited 2014-09-06 17:44
    with Tachyon and a SD card you could read directly from the SD via RAM buffers.
    and if you store the differences instead the 5ms on/off values and use waitxx
    the file can be smaller and the processing faster
  • engineearengineear Posts: 4
    edited 2014-09-20 08:25
    Thanks for the suggestions. Ended up just using a spreadsheet and writing a command for each timestep. Might not be the most efficient but it seems to work.
    CON    
      _clkmode        = xtal1 + pll16x           ' Feedback and PLL multiplier
      _xinfreq        = 5_000_000                ' External oscillator = 5 MHz
        TimeSt        = 20
        
    PUB LedOnOff
         
        dira[0] := 1
        dira[1] := 1
    
    
        
        
        repeat
          if ina[3] == 1                  ' If pushbutton pressed  
    
    
            outa[1] := 0
             outa[0] := 0
            waitcnt(clkfreq/TimeSt + cnt)
            outa[1] := 0
             outa[0] := 0
            waitcnt(clkfreq/TimeSt + cnt)
            outa[1] := 0
             outa[0] := 0
    
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-20 14:15
    It's a little tricky to understand what you're going for without context or your actual data. You did say two pulses. An easy was to get sub-microsecond precision on your pulses is to use a counter; there are two per cog which is convenient for you. You could even -- as the code below illustrates -- launch your pulse generator in its own cog. This code reads pulse-width values from a table. Pulses are expressed in 1us units.
    pri pules_gen | idx1, idx2, t, pw                               ' launch with cognew
    
      idx1 := 0                                                     ' reset pulse indexes
      idx2 := 0
    
      frqa := 1                                                     ' inc phsa +1 each tick           
      ctra := (%00100 << 26) | PULSE_1                              ' setup for NCO mode; output on PULSE_1
      dira[PULSE_1] := 1                                            ' makepin an output  
    
      frqb := 1                        
      ctrb := (%00100 << 26) | PULSE_2   
      dira[PULSE_2] := 1                  
    
      t := cnt                                                      ' sync 5ms timer
      repeat
        repeat while (ina[ENABLE] == 0)                             ' hold while disabled
          phsa := 0                                                 '  prevent false pulse
          phsb := 0
          t := cnt                                                  '  resync loop timer
    
        pw := long[@Pulses1][idx1++]                                ' read pulse width
        if (pw =< 0)                                                ' if end of table
          pw := long[@Pulses1][0]                                   '  read 1st element
          idx1 := 1                                                 '  reset table index
        phsa := pw * -US_001                                        ' start pulse 1
    
        pw := long[@Pulses2][idx2++]  
        if (pw =< 0)                  
          pw := long[@Pulses2][0]     
          idx2 := 1                   
        phsb := pw * -US_001          
    
        waitcnt(t += constant(5 * MS_001))                          ' loop period is 5ms
        
    
    dat { pulse values }
    
    '' Specified in microseconds
    '' -- tables can be different lengths
    '' -- use -1 to specify end of table
    
      Pulses1     long      100, 200, 300, 400, 500, 600, 700, 800, 900, 1000
                  long      -1      
    
      Pulses2     long      1000, 1500, 2000, 2500
                  long      -1
    
  • engineearengineear Posts: 4
    edited 2014-09-20 16:49
    Thanks Jon

    once i understand your code better I think i am going to try and implement it.
    First off, I will try to explain a little better what i am trying to do. The table below shows a part of the pulse cycle I would like to do.

    Pulse.jpg


    Then, I have a question regarding the code you uploaded.
    The following line in your I think puts the Pulse_1 in high for "pw * -US_001"
    phsa := pw * -US_001
    I am not sure whether the US_100 is defined anywhere.
    113 x 435 - 18K
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-20 19:38
    Having seen your data the program can be simpler. I took the Captain Obvious approach and created a table that matches your data. You could have a table with times and transitions, but that's not as easy to follow for beginners. That said, the strategy I used allows you to adjust the length of the table without changing the code (the table has a marker at the end).

    As before, this runs in its own cog -- for grins as I don't know what you're doing with these pulses. When enabled, the code will run through the entire table. If you want the outputs to stop as soon as enable is released, I can show you how to code that (it's easy).
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-21 07:37
    Here's an update to the working code section that lets you specify transitions and hold times. The table is a little tricker to construct, but gives you more flexibility in your output waveforms.
    pri pulse_gen | t, p_table, ledbits, ms
    
      dira[LED1..LED2] := %11                                       ' make outputs
      
      repeat
        outa[LED1..LED2] := %00                                     ' LEDs off  
        t := cnt                                                    ' set delay sync point
        repeat while (ina[ENABLE] == 1)                             ' if enabled
          p_table := @PulseMap                                      ' reset table pointer
          repeat
            ledbits := byte[p_table++]                              ' read bits from table
            ms := byte[p_table++]                                   ' read timing from table
            if (ledbits =< %11)                                     ' if valid bits
              outa[LED1..LED2] := ledbits                           ' update outputs 
              waitcnt(t += (ms * MS_001))                           ' hold 
            else
              quit                                                  ' cycle is complete
    
    
    dat { pulse table }
    
      PulseMap    byte      %00,  5                                 ' 0.000
                  byte      %01, 10                                 ' 0.005
                  byte      %11, 10                                 ' 0.015
                  byte      %10, 20                                 ' 0.025
                  byte      %00, 15                                 ' 0.045
                  byte      %01, 10                                 ' 0.060
                  byte      %10, 10                                 ' 0.070
                  byte      %11,  5                                 ' 0.080
                  byte      %10, 10                                 ' 0.085
                  byte      %00,  5                                 ' 0.095
                          
                  byte      -1,  -1                                 ' end of table
    
Sign In or Register to comment.