Shop OBEX P1 Docs P2 Docs Learn Events
How to output a pulse train while processing — Parallax Forums

How to output a pulse train while processing

GICU812GICU812 Posts: 289
edited 2007-11-29 02:24 in BASIC Stamp
For my project, I need to output a 20khz pulse train at %50 duty cycle AND a 2khz pulse train at 25% duty cycle WHILE processing inputs. Is this even possible with a stamp? Im using a 2p40

confused.gif



What would be the best way of going about this? Sample code would be great, I can modify it for what I need once I get the basic idea figured out.

Thanks,

Adam

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-23 20:37
    No. The Stamps are strictly single threaded processors. They can do only one thing at a time. If several different things are needed and they happen slowly (not your situation), you can interleave things.

    It sounds like you need something like the PWMPAL (see Parallax's webstore).
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2007-10-24 10:11
    Adam -

    There are certainly a number of different Stamp-compatible co-processors that will more than fit your requirements. Ask if you would like more information on same.

    Alternatively, an simple, external 555 timer should be able to provide the pulse train as well.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • BeanBean Posts: 8,129
    edited 2007-10-24 11:42
    The SX48 would also be able to do it using the two hardware timers.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    My goal is to live forever...Or die trying.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    www.hittconsulting.com
    ·
  • GICU812GICU812 Posts: 289
    edited 2007-10-24 12:35
    While the PWMPAL looks great, unfortunately, if my math is correct, it is only capable of 3 duty cycles at 20khz, 0, 50, 100. Would it be possible to interleave 2 10khz pulse trains on the same line by jumpering the lines together? Then I could have DC in 12.5% increments, which would work for me.

    Example: 25% DC

    Train 1:Train2
    - - _ _ : _ _ _ _

    Example 87.5% DC

    - - - - : - - - _

    I didn't mention this granularity initially just for simplicity. I need to be able to at least set the 20 khz DC at either %50 or %25, and control the 2 Khz in least 10% DC increments

    Id prefer an option that would let me use the Stamp 2p40 I have, though I may downsize to a 24 for production. I can even wire the PWMPAL onto my 40 no problem if that works.

    Im curious as to how I could use the 555 timer, but the less hardware the better.

    Thanks,

    Adam
  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-24 15:56
    There are all sorts of ways to do this with external hardware, but, if you want to keep the hardware to a minimum, you should switch to an SX or Propeller. One possible option would be to use the GPIO3 firmware with an AVR coprocessor as supplied with the BS2pe MoBo. The only problem is that the PWM frequency is fixed at around 18KHz, not 20KHz, but the pulse width is adjustable in 255 steps. Have a look at the documentation on the BS2pe MoBo webstore page. The AVR firmware talks to the BS2pe using the 1-Wire protocol which the BS2p40 can also do. There's a schematic of the MoBo and you could just copy the bits around the AVR coprocessor and program your own using the firmware that you can download.
  • GICU812GICU812 Posts: 289
    edited 2007-10-25 15:00
    Actually, what might work best, if I built a dedicated circuit for the 20khz signal, it needs to be normally 50%DC , and switch to %25 when triggered. I didnt realize before that I only needed the two specific DCs on this line. The 2Khz signal, I can maybe interleave into the programming.
  • metron9metron9 Posts: 1,100
    edited 2007-10-25 23:08
    If you want to send me your address i will pop a tiny45 in the mail for you. I programmed it to put out a 20khz and 2khz signal on portb0 and portb1. Also an on off switch on portb2 where high=on and low=off. (Use a 220 ohm resistor from a stamp pin to this pin, just in case you miswire it won't make any smoke)·if you want I could put in sleep modes as well so when off it only draws 2ua or something like that if you are using·battery.



    The red channel is the stamp turning on and off the chip in a loop. The blue channel is the 20khz signal turning on when portb2 goes high.

    Stamp code
    
    Main:
    
    high 10
    
    low 10
    
    goto main
    
     
    
     
    
    This is the code for the tiny45
    
    The lowest frequency external clock i have is 5Mhz resonator. I can send that as well if you like. The 
    
     
    
    [noparse][[/noparse]code]
    
    .include "tn45def.inc"
    
    .def khz2 = r16
    
    
     .org $0000
     rjmp  reset
     rjmp  ext_int0
     rjmp  pcint_0
     rjmp  tim1_compa
     rjmp  tim1_ovf
     rjmp  tim0_ovf
     rjmp  ee_rdy
     rjmp  ana_comp
     rjmp  adc_complete
     rjmp  tim1_compb
     rjmp  tim0_compa
     rjmp  tim0_compb
    
    
    reset:
     LDI  R16,0B00000011
     OUT  DDRB,R16
    
     ldi  r16, low(RAMEND)  
     out  SPL,r16           ; Set Stack Pointer
     ldi  r16, high(RAMEND)
     out  SPH,r16
    
     ldi  r16,(1<<WGM01)
     out  TCCR0A,r16    ;CTC mode
     ldi  r16,(1<<OCIE0A) 
     out  timsk,r16         ;turn on interrupt flag
     ldi  r16,125     ;5million / 125 = 40,000 = 20khz
     out  ocr0a,r16         ;set compare match  
     ldi  r16,(0<<CS02)|(1<<cs00) ;Turn on timer clock
     out  tccr0b,r16  ;
    
     ldi khz2,10 ;for 2khz output
    
    Main:
     cli    ;clear interrupts so timer won't toggle pins
     cbi  portb,0 ;set the ports being used to low
     cbi  portb,1
    OFF:
     sbis  pinb,2  ;skip next instruction if portb,2 is high
     rjmp  OFF  ;loop
     sei    ;turn on interrupts
    ON:
     sbic  pinb,2 ;skip next instruction if portb,2 is low
     rjmp  ON
    rjmp main
    
     
    
    
    ext_int0:
    reti
    pcint_0:
    reti
    tim1_compa:
    reti
    tim1_ovf:
    reti
    tim0_ovf:
    reti
    ee_rdy:
    reti
    ana_comp:
    reti
    adc_complete:
    reti
    tim1_compb:
    reti
    
    tim0_compa:   ;toggles ports 0 and 1 20khz and 2khz
     sbi  pinb,0 ;20khz toggle 
     dec  khz2
     brne tim0_exit
     sbi  pinb,1 ;2khz toggle
     ldi  khz2,10
    tim0_exit:
    
    reti
    
    tim0_compb:
    reti
    
    
    




    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!
    563 x 396 - 9K
  • GICU812GICU812 Posts: 289
    edited 2007-10-30 15:10
    Wow, thanks a lot. Im not sure if it will work for what I need though (that or I just dont understand - which is definitely possible). I guess I was too vauge in the begining, I really didnt think I would get this much help, in my experience, if you go into too much detail, people just ignore your questions, so I thought I would just put out the bear minimum and get some generic responses. That has definitely not been the case, so let me lay out what I need to do here.

    Im controlling an electric motor through a proprietary controller that cannot be modified. This controller expects to see 3 signals, we'll call them A, B and C.

    Signal A is a simple logic switch. Normally high, it is drawn low when the motor is used in any way, simply an on-off switch if you will. I got that one figured out, [noparse];)[/noparse]

    Signal B is essentially another on-off switch, but digital. This is the 20Khz signal. It needs to normally sit at 50%DC. When the motor is used, it needs to be dropped to %25 DC.

    Signal C is the "speed" controller. Its a 2khz signal, resting at 50%DC. For full power, it needs to scale to %90, for full reverse (actually regeneration in this case) it needs to scale to %10 DC. I would be happy with %10 increments but the finer control the better.

    So say I want to demand full power, A needs to drop low, B needs to be 20Khz/25%, C needs to be 2Khz,%90

    Go back to idle, A = high, b=20khz\50%, c=2Khz\50%

    Full regen A=low, b=20Khz\25%, c=2khz\10%

    And obviously C needs to scale so I can set any desired amount of power \ regeneration I want between %10 and %90

    The main stumbling point for me was trying to get that 20khz signal since it is so fast in relation to the stamp.

    At this point, it might be easier just to use external hardware, especially for the 20khz signal, so, since you guys are obviously the experts, you tell me what you would do. I like figuring things out for myself, but this time it might be better to follow your advice.
  • metron9metron9 Posts: 1,100
    edited 2007-10-30 15:55
    I see now what you need to do. The question becomes at what rate do you need to change the duty cycles, I could set up a chip to simply use shift registers from the stamp you would communicate with shiftin and shift out to send the commands.


    An 8 bit PWM signal at a specific frequency can be adjusted in 254 duty cycles in .39% increments

    so you want 50% on B you send 127 at 10% you send 25 for example.

    16 bit timers would give you finer resolution if you need it.

    Would that work?



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!
  • GICU812GICU812 Posts: 289
    edited 2007-10-30 18:24
    That would work great! shift registers would be fine, it doesnt need to be super fast, as long as there is less than a second lag, which I dont think it would be near that.

    I'll be using a single joystick or pot to control the motor. So it wont be super precise, doesnt need to be. I would be happy with 10 increments from 10 to 90 so yea, 254 will be great. At least it will allow for smoother transistions.
  • metron9metron9 Posts: 1,100
    edited 2007-11-01 06:42
    I made a 20khz chip from a tiny45. Here is a video of the output using this code.
    I used the stamps pulsout command for communication. The tiny45 reads the width of the pulse to set the duty cycle.
    You can set from 1 to 99% in 1% increments. Send a pulse of 110 (220us) to turn the pin off (low)
    Should be able to change duty cycles 50 times per second

    http://www.acousticlights.com/20KHZ.html

    outputs from 1 to 100% duty cycle. Over 106 pulsout turns PWM off.

    Since the PWM cycle is 248 ticks at 10mhz there is not an exact step of 1% between duty cycles, also there is some clipping at the top values so that a·off cycle of 1 and on cycle of 247 (1/247) gives almost 100% on.· If you send a longer pulse the program will hold off reading any new·puls widths until a low signal is again seen on the line.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    ' {$PORT COM1}
    i VAR Byte
    main:
    FOR I = 0 TO 106 STEP 1
     PULSOUT 1,I
     DEBUG DEC I,CR
     PAUSE 100
    NEXT
    GOTO main
    
    

    Problem is , when i went to do the second timer, it's output is on one of the resonators pins as well as it doesn't have the correct setup for this type of PWM. I will just use a tiny2313 its a 20pin chip instead of 8. By this weekend i will have one ready to go. The 2313 also has a USART so I will use serial communication, that will allow me to make a generic chip that has 4 PWM outputs so i will add the ability to set the frequency and pulse width, like a mini pwmpal I guess.



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!

    Post Edited (metron9) : 11/1/2007 6:53:47 AM GMT
  • GICU812GICU812 Posts: 289
    edited 2007-11-05 13:26
    Sounds great, let me know how it works out. Im still tweaking with the other inputs Im going to have, so im not in a rush.
  • GICU812GICU812 Posts: 289
    edited 2007-11-12 13:26
    Is it going to work? If not, no biggie, I can find another way, but yours sounds like the best.


    I picked up a couple of 555 Timers, not knowing the first thing about them, but they're cheap ya know.

    Reading about them, I guess you cannot make a pulse train in excess of 50% DC, is this correct?
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-12 16:08
    What do you mean by "50% DC"? If you're using just a single 555, you're limited in the range of on/off times.
    If you use two or a dual unit, you use one as a monostable that puts out a variable width pulse and you use
    the other as an asynchronous trigger that sets the repetition rate. The two settings are independent and I
    think the width can be quite close to the repetition rate.
  • metron9metron9 Posts: 1,100
    edited 2007-11-12 18:32
    Sorry, I am just getting back to normal, we had a robbery last week and after looking at all the filth that lives around my town I just sort of stared into space for a while asking what's the point of it all. I had to make some home bugler alarms for my out buildings. Over 5000 people a year in our county are run through the jail house. It's pathetic we have to live on the same planet as these morons.

    I will finish that chip for you tonight.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!
  • GICU812GICU812 Posts: 289
    edited 2007-11-12 18:37
    I live in a prison town, believe me I know. They get sent up and their families come here to be close for visitation, then when they get released they all just stay here. Makes for a great demographic, there is about half the town I avoid whenever possible

    Town motto is Keep the doors locked and the guns loaded.

    Good news is you obviously have the skills to make a great security system cheap. I've always wanted to interface one to a cell phone, so it could call or text me with the status, I just could never justify the expense of dedicating a cell phone to it.

    About the 555 timer, I could have read the datasheet wrong I dont know. I picked up a 555 and a 556 dual timer.
  • FranklinFranklin Posts: 4,747
    edited 2007-11-12 19:37
    Message on cell phone <you have just been robbed, please come home to assess the damage.>

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Stephen
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2007-11-12 20:01
    It's not just big cities and prison towns. I live in a small seaport town at the dead end of a peninsula, where everybody used to leave their doors unlocked. I've been robbed three times. The same wetsuit got taken twice. 'Got it back from a neighboring county's sheriff's department after the first robbery; 'haven't seen it since the second one. A large part of the current problem is due to the meth epidemic, and that's happening everywhere, unfortunately.

    -Phil
  • metron9metron9 Posts: 1,100
    edited 2007-11-13 09:47
    Ok finished. I am going to give you two 8 pin chips (Tiny45's) and use their internal 8mhz oscillators. If you need more than a few percent accuracy a crystal can be used but i would need to set a fuse bit and an 8MHZ crystal or oscillator would need to be used. I only see at most a 100 hz difference and usally 20 or 30 hz variance in the 20khz timer. Only about 5hz variance in the 2khz timer.

    Since i don't have any chips with three timers I decided to use 2 chips. You will need two stamp pins for setting the duty cycle and one pin to connect to the enable pins assuming you want to enable and disable both chips at the same time. An alternitive to the enable pin would be to set a lower limit of a few percent to turn off the output. Let me know if you want to do that instead of the enable pins.



    The 20khz input pulse from pulsout ranges from 1 to 99 for 1 to 99% duty cycle
    The 2khz input pulse from pulsout ranges from 1 to 124 for 1 to 99% duty cycle

    The hardware timer is an 8 bit timer for both of them. The 20khz rolls over at 202 and the 2khz rolls over at 249.

    The input pulse from the stamp is 2us per unit. I used a second timer to time the pulse with that timer divided by 8 so the timer value is put directly in the compare register of timer 0.

    I need to do a little bit more code to allow for the numbers outside each frequencies range, for example if the timer goes over 201 while reading the pulsout from the stamp·it will be reduced to 201 in the case of the 20khz timer. Also I will put in a enable pin to turn on and off the output. When off the pins will all be set to input.

    I will try and send them Wednesday.

    The only code that runs is the interrupt code that loads the duty cycle compare register. I simply reset the timer to 0 and wait for the the pin to go low to store the value. The timer is using mode 5 PWM phase correct.

    i initially tried to make a two timer software solution but I don't have any chips fast enough. I suppose you could do it with an sx but the power needed to run that chip is pretty high if you are using a battery.

    Forgot to ask if you need a sleep mode to conserve power.

    I also programmed up a tiny2313 that allows serial input from the stamp and gives you 4 PWM outputs that run at 28khz. You simply use SEROUT 0, baud, [noparse][[/noparse]i,j,k,l] to set all 4 PWM outputs. Glitch free at 38.4kbs. 255 different duty cycles for 1% to 99%. I am going to·configure·some chip select pins so you can connect up to 4 of them (16 PWM channels) on one serial line. In that case you would need to send 16 bytes of data and each chip would take the 4 bytes assigned to it. Chip 1, first 4 bytes, chip 2 next 4 bytes etc. A simple High/Low resets the chips byte counters. These work great for dimming LED's.

    i will toss in one of those if you would like to test it out for me.



    ext_int0:
    out tcnt1,timestart
    int0lp:
    sbic pinb,2
    rjmp int0lp
    in inttime,tcnt1
    out ocr0b,inttime
    reti

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!

    Post Edited (metron9) : 11/13/2007 10:02:44 AM GMT
  • GICU812GICU812 Posts: 289
    edited 2007-11-13 13:32
    I'll be more than happy to test anything I can for you.

    As of right now I have no foreseeable need for more than 2 outputs, so I should be okay. Two chips will be fine, im not real crunched for space.

    As for the lower enable, I have no need for 20Khz DC below 25%, or the 2khz below, say, 5% DC so if you can work with that, less pins is always better. However, since I am intercepting a signal, I'll be using a 2 pole relay to break the two wires and connect my stamp, so I can just use stamp output to do both the relay and enable. Are they high enable or low? Doesnt matter I suppose. Any suggestions on a good place to get a 2 pole relay?

    I also need some A\D converters. I need to snoop a couple of signals, but its absolutely imperative I do not alter the signals, even the least. Anyone suggest a chip that can handle multiple inputs? I suppose I could just get a standard A\D and a multiplexer, didnt know if there was a all in one chip. I wouldnt need more than 8 signals.
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-13 15:33
    There are all sorts of multi-channel ADCs. The MAX1270 that Parallax sells is a 12 bit 8 channel device.
  • metron9metron9 Posts: 1,100
    edited 2007-11-13 15:38
    Typically for an ATMEL chip when using an ADC the chip is put to sleep and the ADC does it's measurement to eliminate noise. If you have lot's of pin activity especially with motors you may have a more complicated design including both digital ground and analogue ground and other filtering aspects. I don't know much about that kind of design. You may want to post the ovrall design , speed's of ADC conversions required as well as the resolutiion you need in your ADC conversions so the folks here can tweek your initial layout or point out obvioius potential problems.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!
  • GICU812GICU812 Posts: 289
    edited 2007-11-13 19:45
    Okay Guys, heres the basic idea. Please feel free to advise on anything you see that looks wrong, or where you could improve. Given I probably dont have the connections right to the ADC on here, it was just a generic Visio object.
    8886_.jpg

    I can email the Visio to anyone who wants it, if I really messed up, lol

    Post Edited (GICU812) : 11/13/2007 8:04:55 PM GMT
  • GICU812GICU812 Posts: 289
    edited 2007-11-13 19:55
    The ADC itself will be housed with the stamp away from any sources of EMI. The measurements are mostly insigifigant, having a little error isnt going to effect the overall operation, what is critical is that I do not modify the original signals. As for speed, 25 samples per second would be sufficient. 100 might be nice.
  • metron9metron9 Posts: 1,100
    edited 2007-11-14 07:00
    Here is the 2khz output from the file below

    You can set the duty cycle when the chip is off as well. For example set to 50% then turn on and off it will hold the last pulse width. Set the pulse with to 0 before enabeling the chip so you don't have an unknown duty cycle.


    http://www.acousticlights.com/2khzscope.html
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    ' {$PORT COM1}
    i VAR Byte
    main:
    HIGH 3  'turn on
    FOR i=1 TO 127
     PULSOUT 0,i
    NEXT
    FOR i=127 TO 1
     PULSOUT 0,i
     PAUSE 10
    NEXT
    LOW 3 'turn off
    PAUSE 1000
    GOTO main
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Think Inside the box first and if that doesn't work..
    Re-arrange what's inside the box then...
    Think outside the BOX!

    Post Edited (metron9) : 11/14/2007 8:03:54 AM GMT
  • GICU812GICU812 Posts: 289
    edited 2007-11-14 15:01
    Great!

    I PMed you my info.
  • GICU812GICU812 Posts: 289
    edited 2007-11-20 20:33
    So this will work then?
    9050_.jpg
  • GICU812GICU812 Posts: 289
    edited 2007-11-28 15:21
    Well after ironing out a few bugs, I got it working.... Sorta.

    If I leave the original ECM signals on the line, and superimpose my new ones over top, it works okay, It will accellerate at my commanded level, though I dont think it will decelerate. This is probably because while I can always raise the level with more DC, I cannot lower the level below what the ECM is putting on the line, which is normally %50 for "neutral"

    The problem comes when I try to use the circut as designed. When I cut off the ECM from the path, and just use my signals, it will either instantly go full accell, or full regeneration, or sometimes nothing, then a second later, trip the IMA warning light and disable the system. Looking at them on the scope, the signals are identical, though my supplemented signal's low level is a few hundred Mv below the ECM's "low" signal.

    I tried just hijacking one signal or the other, and while I wont always get the accell\regen response, it always trips the IMA light and shuts down the system. Its obvious it doesnt like my signals. To prove it wasnt the switchover blip, I can flip the relays for up to 1 second, then flip them back, and it wont trip the IMA light, even over and over again, but if it sees my signals for more than 1 second, it will trip.

    I thought maybe the ECM was seeing a dead line and signaling the error, so I put a pullup resistor to 5v on the ECM side of the line. I will have to try this again tonight, as I was in a hurry at the time, and I just got a dead line on the scope when I checked it still. To explain, the MCM pulls the line high through a resistor, then the ECM pulses the line low to communicate. I dont think the ECM could sense a dead line, but I dont have details to that effect either. But since I am just dropping the ECM line, it might be an idea.


    Or it could be in the signals. how do I raise the low threshold of my signal, a resistor in line to ground? I dont understand why my signals would be getting pulled lower than the ECM's signaling does in the first place...
  • GICU812GICU812 Posts: 289
    edited 2007-11-29 02:24
    Figured it out. I transposed some values in my pinout spreadsheet, 2khz blue went to ECM, blue\white to MCM, I switched them, allong with the 20khn signal, so I wasnt feeding the MCM anything.

    Now it works fine, except I cannot get it to regen yet, I think I need to change some ordering in the code, that outta do it.

    Thanks a lot for all the help!
Sign In or Register to comment.