Interrupt 100 times faster in simulator

stan74

Senior Member
Hi,confused again here.I set up code to run a unipolar stepper motor from timer interrupt.It works in the simulator but in pic it runs every 10 seconds.The stepper driver has 4 leds that show the status of the motor inputs and the pin sequence is correct,changing every 10 seconds.
The stepper code works as a subroutine ie motor turns each way. Why is the interrupt not more often? I'm stumped again.Any help welcome.I'm thinking of another hobby.
Code:
[color=Green];28x2 A.0 to A3 are unipolar motor pins [/color]
[color=Navy]#picaxe [/color][color=Black]28x2[/color]
[color=Blue]setfreq m16
symbol [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Purple]b0[/color][color=Black]:[/color][color=Blue]symbol [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Purple]b1[/color][color=Black]:[/color][color=Blue]symbol [/color][color=Purple]outbyte[/color][color=DarkCyan]=[/color][color=Purple]b2[/color][color=Black]:[/color][color=Blue]symbol [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Purple]b3[/color][color=Black]:[/color][color=Blue]symbol [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]b4[/color]
[color=Blue]let [/color][color=Purple]dirsa[/color][color=DarkCyan]=[/color][color=Navy]%11111111[/color][color=Black]:[/color][color=Blue]let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1[/color][color=Black]:[/color][color=Blue]let [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]1[/color][color=Black]:[/color][color=Blue]let [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Navy]1[/color][color=Black]:[/color][color=Blue]let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed[/color]


[color=Blue]settimer count [/color][color=Navy]65530    [/color][color=Green]; settimer to count mode[/color]
[color=Blue]settimer t1s_16
gosub [/color][color=Black]interrupt_Enable

main:[/color]
[color=Blue]do[/color]
[color=Green];let direc=1
;pause 2000
;let direc=0
;pause 2000[/color]
[color=Blue]loop  

 
interrupt:
if [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]>[/color][color=Navy]0 [/color][color=Blue]then dec [/color][color=Purple]tempmotorspeed[/color][color=Black]:[/color][color=Blue]goto [/color][color=Black]interrupt_enable:[/color][color=Blue]endif
let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed[/color]
[color=Blue]if [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then inc [/color][color=Purple]posrotor[/color][color=Black]:[/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8 [/color][color=Blue]then let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1[/color][color=Black]:[/color][color=Blue]endif 
else[/color][color=Black]:[/color][color=Blue]dec [/color][color=Purple]posrotor[/color][color=Black]:[/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8[/color][color=Black]:[/color][color=Blue]endif
endif
lookup [/color][color=Purple]posrotor[/color][color=Black],[/color][color=Blue]([/color][color=Navy]0[/color][color=Black],[/color][color=Navy]%00000011[/color][color=Black],[/color][color=Navy]%00000010[/color][color=Black],[/color][color=Navy]%00000110[/color][color=Black],[/color][color=Navy]%00000100[/color][color=Black],[/color][color=Navy]%00001100[/color][color=Black],[/color][color=Navy]%00001000[/color][color=Black],[/color][color=Navy]%00001001[/color][color=Blue])[/color][color=Black],[/color][color=Purple]outbyte
pinsa[/color][color=DarkCyan]=[/color][color=Purple]outbyte[/color]

[color=Black]interrupt_Enable:[/color]
[color=Blue]setintflags [/color][color=Navy]%10000000[/color][color=Black], [/color][color=Navy]%10000000[/color]
[color=Purple]timer[/color][color=DarkCyan]=[/color][color=Navy]65530[/color]
[color=Purple]toflag [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]return [/color]
 
Last edited:

hippy

Technical Support
Staff member
When I run the following test code under simulation or on a real PICAXE-28X2 I get an interrupt every 6 seconds as would be expected -

Code:
#picaxe 28x2
#Terminal 19200

setfreq m16

settimer t1s_16
gosub interrupt_Enable

main:
do
loop  

 
interrupt:

  w0 = w0 + 1
  SerTxd( #w0, " ")

interrupt_Enable:
setintflags %10000000, %10000000
timer=65530
toflag = 0
return
 

Technical

Technical Support
Staff member
Code:
if tempmotorspeed>0 then dec tempmotorspeed
goto interrupt_enable
...
or

Code:
if tempmotorspeed>0 then 
  dec tempmotorspeed
  goto interrupt_enable
  ...
They are two different things and you should use a colon line separator after then (or even better new lines) to make sure both humans and the compiler understand you correctly.

Code:
if tempmotorspeed>0 then 
  dec tempmotorspeed 
  goto interrupt_enable
end if
 

stan74

Senior Member
Not a chance, Pal!

I'll let others help out here, since I've never used an interrupt.
So how do YOU use stepper motors... or do you use high geared easy peasey dc motors :) The tank dual motors at 220:1 are carp..and it took an hour to build with "instructions". The stepper motor moves tidy..torky but needing 1 of 7 patterns to 4 pins for one motor..can use the other unused transistors on the driver chip to make not gates to drive the lines ie use only 2 lines...but only for 4 waves..not 7..ie different 1/2 wave or summat, totally new moi,erste stepper experiment,didn't have this when I woz in skool.
All the joys of a pic in an easy to use format that doesn't have negative numbers.Even sincliar zx besic had that.
You have probably seen the goody bag of arduino sensors on ebay,not enough hours to play with them all.3 axis inertia sensor needs minus numbers so don't get one,same oled ,needs minus numbers to make line draw algorithm to work...I tried sooooo hard. Why don't I use my RPi's to make a robot??? r u on facebook erco?
 

erco

Senior Member
Transistors? You do know about the world's cheapest steppers & ULN2003 drivers on Ebay?

http://www.ebay.com/itm/ULN2003-chip-Module-Stepper-Motor-Driver-Board-Test-Board-For-Arduino-Mega-NEW-/332039552989

http://www.ebay.com/itm/ULN2003-ULN2003AN-Stepper-Motor-Driver-Board-Module-for-28BYJ-48-5V-12V-Arduino-/262130708059

http://www.ebay.com/itm/5V-28BYJ-48-Stepper-Motor-Driver-Test-Module-Board-with-ULN2003-Chip-Set-Hotsale-/371742138940

Using/mastering steppers is a rite of passage for budding roboticists. That stepper above is cheap but frustrating. Skips steps easily and the oddball gear ratio makes it very difficult to get precision. And in general, steppers needs of I/O pins or a dedicated controller chip. Here are my few stepper projects;

https://www.youtube.com/watch?v=SYi0Cs8jJqM

https://www.youtube.com/watch?v=TLdkKKMfUP0

https://www.youtube.com/watch?v=sogHSr37BsE

 

stan74

Senior Member
I'll check that out technical. I just wrote it short. What I want is the interrupt to happen say every few mS,enough to move the stepper while the main prog does stuff.My first use of a stepper motor..the 1/2 wave-4 pattern has no torque.
I could use a gosub to move the motor but it's pure slow in a do:gosub move:loop,so not an option in a prog that does much.
As an option I tried start0 and start1 to hold the motor code...but to no avail.least I tried.
 

erco

Senior Member
Check out stepper motor full step, half step & wave drive patterns: https://en.wikipedia.org/wiki/Stepper_motor

No shame in driving a 5V stepper with 9-12 volts to improve speed/torque, it's quite common. Just switch fast, keep moving and don't leave the coils on very long. Turn everything OFF as soon as you stop.
 

stan74

Senior Member
Transistors? You do know about the world's cheapest steppers & ULN2003 drivers on Ebay?
Far out man..or dude.I guess you think steppers are ok a bit,kinda like a continuous stepper...but "a bit harder :)"
I'm ebayed out a bit for now,sharp IR sensors soon as well.Making a tank bot for grandson with carp tamiya.SAM_1177.JPG
 

erco

Senior Member
Nice looking tank bot. Reminds me of one I built with those parts, 4 different configurations.

 

stan74

Senior Member
When I run the following test code under simulation or on a real PICAXE-28X2 I get an interrupt every 6 seconds as would be expected -

Code:
#picaxe 28x2
#Terminal 19200

setfreq m16

settimer t1s_16
gosub interrupt_Enable

main:
do
loop  

 
interrupt:

  w0 = w0 + 1
  SerTxd( #w0, " ")

interrupt_Enable:
setintflags %10000000, %10000000
timer=65530
toflag = 0
return
I'm assuming I pre-load timer with how many 40uS whatever ticks < 65535 and the interrupt happens and then it is retriggered with the code at the end of the interrupt.So timer=65530 is 6 x 40us ticks, but it's not.Please could you give interrupt code that goes to interrupt every 200 us.. if that would run a uni polar stepper motor. First time I've used the simulator.
 

stan74

Senior Member
Nice looking tank bot. Reminds me of one I built with those parts, 4 different configurations.

Yeah. Want the tracks not too tight/not too slack or the links bend.Something that works on a table.Mine start in the living room and end up wandering around the kitchen.They come back sometimes. My kit came with enough cogs,axles and track to make 2 tank bots.
Bots looking like Wall-E which is a waste of track but more aesthetically pleasing (cooler), a us ranger is better vertical with the mic at the bottom.Need clear acrylic/perspex recycle not buy 6 foot x 2 foot sheet..too mean and recycling is safe.
 

stan74

Senior Member
Code:
if tempmotorspeed>0 then dec tempmotorspeed
goto interrupt_enable
...
or

Code:
if tempmotorspeed>0 then 
  dec tempmotorspeed
  goto interrupt_enable
  ...
They are two different things and you should use a colon line separator after then (or even better new lines) to make sure both humans and the compiler understand you correctly.

Code:
if tempmotorspeed>0 then 
  dec tempmotorspeed 
  goto interrupt_enable
end if
This is the same but more readable.Still slowww and changed to use parallel programming but does nothing.
Code:
[color=Navy]#picaxe [/color][color=Black]28x2[/color]

[color=Blue]setfreq m16
symbol [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Purple]b0[/color]
[color=Blue]symbol [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Purple]b1[/color]
[color=Blue]symbol [/color][color=Purple]outbyte[/color][color=DarkCyan]=[/color][color=Purple]b2[/color]
[color=Blue]symbol [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Purple]b3[/color]
[color=Blue]symbol [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]b4[/color]
[color=Blue]let [/color][color=Purple]dirsa[/color][color=DarkCyan]=[/color][color=Navy]%11111111[/color]
[color=Blue]let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]let [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]let [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed[/color]

[color=Blue]start0:
do[/color]
[color=Green];let direc=1
;pause 2000
;let direc=0
;pause 2000[/color]
[color=Blue]loop  
 
start1:
if [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
      dec [/color][color=Purple]tempmotorspeed
      [/color][color=Blue]goto [/color][color=Black]start1[/color]
[color=Blue]endif
let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed[/color]
[color=Blue]if [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
      inc [/color][color=Purple]posrotor
      [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]>[/color][color=Navy]8 [/color][color=Blue]then
            let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1
      [/color][color=Blue]endif 
else
      dec [/color][color=Purple]posrotor
      [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]<[/color][color=Navy]1 [/color][color=Blue]then
            let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8
      [/color][color=Blue]endif
endif
lookup [/color][color=Purple]posrotor[/color][color=Black],[/color][color=Blue]([/color][color=Navy]0[/color][color=Black],[/color][color=Navy]%00000011[/color][color=Black],[/color][color=Navy]%00000010[/color][color=Black],[/color][color=Navy]%00000110[/color][color=Black],[/color][color=Navy]%00000100[/color][color=Black],[/color][color=Navy]%00001100[/color][color=Black],[/color][color=Navy]%00001000[/color][color=Black],[/color][color=Navy]%00001001[/color][color=Blue])[/color][color=Black],[/color][color=Purple]outbyte
pinsa[/color][color=DarkCyan]=[/color][color=Purple]outbyte[/color]
[color=Blue]goto [/color][color=Black]start1[/color]
 

stan74

Senior Member
If I can't solve this I've a 20x2 I could use as a slave.A lot of bother or just go forward one wheel rotation and scan and manoeuvre..yawn.I like them a bit more dynamic like this which can see both directions so doesn't get caught out. Like bot 1, rangefinder scans and moves each program loop.SAM_1186.JPG
 

inglewoodpete

Senior Member
This is the same but more readable.Still slowww and changed to use parallel programming but does nothing.
You need to use a different technique with X2 chips. The "parallel" programming technique is only possible on M2-series PICAXEs.

Edit: Persist with your original code. See next post.
 
Last edited:

inglewoodpete

Senior Member
Code:
[color=Blue]settimer count [/color][color=Navy]65530    [/color][color=Green]; settimer to count mode[/color]
[color=Blue]settimer t1s_16
gosub [/color][color=Black]interrupt_Enable[/color]
The timer can only be configured one way. SetTimer Count <value> is expecting to count pulses on Pin C.0 (the manual is not very clear on this). Alternatively, SetTimer t1s_16 will tick once every second with 16MHz clock. Since this command is last in the startup, this mode prevails.

You initialise the timer's rollover value in your interrupt enable routine to 65530. The first interrupt will occur once every 65536 - 65530 or 6 seconds. That will be slow!
Code:
[color=Black]interrupt_Enable:[/color]
[color=Blue]setintflags [/color][color=Navy]%10000000[/color][color=Black], [/color][color=Navy]%10000000[/color]
[color=Purple]timer[/color][color=DarkCyan]=[/color][color=Navy]65530[/color]
[color=Purple]toflag [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]return [/color]
Depending on how often interrupts are occurring, the TOFlag should be reset promptly on entering the interrupt routine and the SetIntFlags should the very last command to be executed before exiting.
 

hippy

Technical Support
Staff member
I'm assuming I pre-load timer with how many 40uS whatever ticks < 65535 and the interrupt happens and then it is retriggered with the code at the end of the interrupt.So timer=65530 is 6 x 40us ticks, but it's not.
There are two parts to the timer. There is an internal counter and "SETTIMER value" determines how quickly this counter exceeds its maximum. When the counter exceeds its maximum it will increment the 'timer' variable. When the 'timer' variable exceeds its maximum the interrupt will occur.

"SETTIMER t1_16" means increment the counter at a rate that it exceeds its maximum every second. 'timer' is therefore incremented every second'. 'timer' starts at 65530 so it requires counter exceeding its maximum six times before the interrupt occurs.


Please could you give interrupt code that goes to interrupt every 200 us.
At 16MHz the counter increments every 16us. 200/16 = 12, 65536-12 = 65524 ...

Code:
[b]SetTimer 65524[/b]
Gosub Interrupt_Enable
Do
Loop

Interrupt:

Interrupt_Enable:
  SetIntFlags %10000000, %10000000
  [b]timer = 65535[/b]
  toFlag = 0
  Return
That is untested and it can be difficult to tweak fast interrupts to get the timing right.
 

stan74

Senior Member
I think a timer interrupt can only be every 1 second or longer. I read assembler is interpreted. Could a real Interrupt beset up? I could code it.
Any road, I set up 1KHz pwm on pin B.0 and connected B.0 to B.7 via 1 K resistor and set up hardware interrupt to trigger on B.7 high.
It works and the motor is turning flat out I reckon. Problem is the main program loop is hardly ever serviced. I found the same when I used 2 slotted decoder wheels.Oh well, it was an interesting few hours. Here's my code for unipolar people, hope it's useful.
Code:
[color=Green];28x2 A.0 to A3 are unipolar motor pins [/color]
[color=Navy]#picaxe [/color][color=Black]28x2[/color]
[color=Blue]setfreq m16
symbol [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Purple]b0[/color]
[color=Blue]symbol [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Purple]b1[/color]
[color=Blue]symbol [/color][color=Purple]outbyte[/color][color=DarkCyan]=[/color][color=Purple]b2[/color]
[color=Blue]symbol [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Purple]b3[/color]
[color=Blue]symbol [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]b4[/color]
[color=Blue]let [/color][color=Purple]dirsa[/color][color=DarkCyan]=[/color][color=Navy]%11111111[/color]
[color=Blue]let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]let [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]let [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed[/color]

[color=Blue]pwmout pwmdiv16[/color][color=Black], [/color][color=Blue]B.0[/color][color=Black], [/color][color=Navy]249[/color][color=Black], [/color][color=Navy]499 [/color][color=Green]; 1KHz out on B.0[/color]
[color=Blue]pwmduty B.0[/color][color=Black],[/color][color=Navy]499[/color]
[color=Blue]setint [/color][color=Navy]%10000000[/color][color=Black],[/color][color=Navy]%10000000[/color][color=Black],B [/color][color=Green]; B.7 gets pwm pulses from B.0[/color]
[color=Blue]gosub [/color][color=Black]interrupt_Enable [/color][color=Green];------ and triggers an interrupt to move motor[/color]
[color=Black]main:[/color][color=Green]; stick any code here[/color]
[color=Blue]do[/color]
[color=Green];let direc=1
;pause 2000
;let direc=0
;pause 2000[/color]
[color=Blue]loop  
 
interrupt:[/color][color=Green]; motor is taken care of,happy days[/color]
[color=Blue]if [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
      dec [/color][color=Purple]tempmotorspeed
      [/color][color=Blue]goto [/color][color=Black]interrupt_enable[/color]
[color=Blue]endif
let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed[/color]
[color=Blue]if [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
      inc [/color][color=Purple]posrotor
      [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]>[/color][color=Navy]8 [/color][color=Blue]then
            let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1
      [/color][color=Blue]endif 
else
      dec [/color][color=Purple]posrotor
      [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]<[/color][color=Navy]1 [/color][color=Blue]then
      let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8
      [/color][color=Blue]endif
endif
lookup [/color][color=Purple]posrotor[/color][color=Black],[/color][color=Blue]([/color][color=Navy]0[/color][color=Black],[/color][color=Navy]%00000011[/color][color=Black],[/color][color=Navy]%00000010[/color][color=Black],[/color][color=Navy]%00000110[/color][color=Black],[/color][color=Navy]%00000100[/color][color=Black],[/color][color=Navy]%00001100[/color][color=Black],[/color][color=Navy]%00001000[/color][color=Black],[/color][color=Navy]%00001001[/color][color=Blue])[/color][color=Black],[/color][color=Purple]outbyte
pinsa[/color][color=DarkCyan]=[/color][color=Purple]outbyte[/color]

[color=Black]interrupt_Enable:[/color]
[color=Blue]setint [/color][color=Navy]%10000000[/color][color=Black],[/color][color=Navy]%10000000[/color][color=Black],B[/color]
[color=Blue]return 




      [/color]
 

hippy

Technical Support
Staff member
I think a timer interrupt can only be every 1 second or longer.
No. The following interupts every half a second, increments the displayed count by 10 in every 5 seconds.

I suspect you aren't absorbing what the manual says and how things were described in post 19.

We are going to increment the internal counter (minor tick) every half a second. 500ms = 500000us which, with 1 minor tick every 16us at 16MHz, means we need 500000/16 = 31250 minor ticks per half second. 65536 - 31250 = 34286 which is our SETTIMER preload value.

Every half second our minor tick count will overflow, giving a major tick, incrementing 'timer'. When 'timer' overflows it generates an interrupt so we set it to 65535 so it overflows on the first major tick.

Code:
#picaxe 28x2
#terminal 19200

setfreq m16

[b]settimer 34286[/b]
gosub interrupt_Enable

main:
do
loop  

interrupt:

  w0 = w0 + 1
  SerTxd( #w0, " ")

interrupt_Enable:
  setintflags %10000000, %10000000
  [b]timer = 65535[/b]
  toflag = 0
  return
 

stan74

Senior Member
I can get an interrupt every 1/2 second but I'll stand in the rain for charity if you can post code that runs at 100 Hz. I think that's why the hardware option I've used has been posted.In your code settimer 34286, change to 65534,24,34 still 1 sec, I just tried it, not the stimulator (erco fnarr,fnarr lost in translation),real picaxe. How can 1/2 a second be changed to 1/100th second. I reckon stepper motors should be avoided for a tranquil life.Thanks for your time hippy,much appreciated.
 

stan74

Senior Member
I have noticed that setting the interrupt to 244hz with setfreq m4 the 4 leds on the driver board were visibly flickering rather than constantly lit suggesting a frequency of < 50Hz so I scoped the pwm and it said 245 Hz.So I tried 500Hz..still flickering.1KHz no flicker.So I scoped the pins C0 to C4 to the motor and they are pulsing at 53Hz. ok the pin might be on 1 in 7 but something's wrong.
See what I meant about steppers?
 

hippy

Technical Support
Staff member
I can get an interrupt every 1/2 second but I'll stand in the rain for charity if you can post code that runs at 100 Hz.
Take a brolly ... :)

10ms = 10000us
10000/16 = 625
65536 - 625 = 64911

This interrupts and increment the w0 count every 10ms, outputs an asterisk every 100 interrupts, one every second ...

Code:
#picaxe 28x2
#terminal 19200

setfreq m16

settimer 64911
gosub interrupt_Enable

main:
do
loop  

interrupt:

  w0 = w0 + 1 // 100
  if w0 = 0 Then
    sertxd( "*" )
  end if

interrupt_Enable:
  setintflags %10000000, %10000000
  timer = 65535
  toflag = 0
  return
For 200Hz ...

5ms = 5000us
5000/16 = 312
65536 - 312 = 65224

And change the //100 to //200
 

stan74

Senior Member
Gives a * every second.This shows nothing scoping b.6.
Code:
[color=Navy]#picaxe [/color][color=Black]28x2[/color]
[color=Blue]setfreq m16
settimer [/color][color=Navy]64911[/color]
[color=Blue]gosub [/color][color=Black]interrupt_Enable
main:[/color]
[color=Blue]do
loop  
interrupt:
for [/color][color=Purple]b10 [/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]to [/color][color=Navy]100[/color]
[color=Blue]high b.6
low b.6
next [/color][color=Purple]b10[/color]
[color=Blue]return[/color]
[color=Black]interrupt_Enable:
  [/color][color=Blue]setintflags [/color][color=Navy]%10000000[/color][color=Black], [/color][color=Navy]%10000000
  [/color][color=Purple]timer [/color][color=DarkCyan]= [/color][color=Navy]65535
  [/color][color=Purple]toflag [/color][color=DarkCyan]= [/color][color=Navy]0
  [/color][color=Blue]return[/color]
 

stan74

Senior Member
Pause instead of the for:next and the code does nothing.As is motor turns 1/4 one way then 1/2 the other way, 1/4 then 1/2 and so on???
Code:
[color=Blue]pwmout pwmdiv16[/color][color=Black], [/color][color=Blue]B.0[/color][color=Black], [/color][color=Navy]249[/color][color=Black], [/color][color=Navy]499[/color]
[color=Blue]pwmduty B.0[/color][color=Black],[/color][color=Navy]499[/color]
[color=Blue]setint [/color][color=Navy]%10000000[/color][color=Black],[/color][color=Navy]%10000000[/color][color=Black],B [/color][color=Green]; B.7 gets pwm pulses from B.0[/color]
[color=Blue]gosub [/color][color=Black]interrupt_Enable [/color][color=Green];------ and triggers an interrupt to move motor[/color]
[color=Black]main:[/color]
[color=Blue]do
setint off
let [/color][color=Black]direc[/color][color=DarkCyan]=[/color][color=Navy]1[/color]
[color=Blue]setint [/color][color=Navy]%10000000[/color][color=Black],[/color][color=Navy]%10000000[/color][color=Black],B[/color]

[color=Blue]for [/color][color=Purple]w5 [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]to [/color][color=Navy]1000[/color][color=Black]:[/color][color=Blue]next [/color][color=Purple]w5[/color]

[color=Blue]setint off
let [/color][color=Black]direc[/color][color=DarkCyan]=[/color][color=Navy]0[/color]
[color=Blue]setint [/color][color=Navy]%10000000[/color][color=Black],[/color][color=Navy]%10000000[/color][color=Black],B[/color]

[color=Blue]for [/color][color=Purple]w5 [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]to [/color][color=Navy]1000[/color][color=Black]:[/color][color=Blue]next [/color][color=Purple]w5[/color]
[color=Blue]loop[/color]
 

stan74

Senior Member
I think close this thread,so hippy can get on.It's been interesting.I still believe you can't use a timer interrupt to turn a led on and of fast enough that it looks constantly lit..50Hz. I'll move the motor 100 times,take range finder reading,act or move servo and repeat. The wheel moves 1/3 rpsec and you don't notice 10mS breaks.Thanks all.
 

hippy

Technical Support
Staff member
This shows nothing scoping b.6
Probably because of the RETURN without re-enabling interrupts. Unless you are quick enough to catch the initial pulses out of B.6 on the first interrupt you won't see any.
 

inglewoodpete

Senior Member
The following code is based on Stan's code posted in #1. The added code is taken directly from another project that I completed a few years ago.

I have included the flashing of the Yellow led to watch the interrupt routine on the oscilloscope. It flashes faster than these human eyes can detect unless I shake my head back and forth.
Code:
[color=Green];28x2 A.0 to A3 are unipolar motor pins [/color]
[color=Navy]#picaxe [/color][color=Black]28x2[/color]
[color=Blue]Symbol oYellowLED       [/color][color=DarkCyan]= [/color][color=Blue]C.2

symbol [/color][color=Purple]posrotor         [/color][color=DarkCyan]= [/color][color=Purple]b0[/color]
[color=Blue]symbol [/color][color=Purple]direc            [/color][color=DarkCyan]= [/color][color=Purple]b1[/color]
[color=Blue]symbol [/color][color=Purple]outbyte          [/color][color=DarkCyan]= [/color][color=Purple]b2[/color]
[color=Blue]symbol [/color][color=Purple]motorspeed       [/color][color=DarkCyan]= [/color][color=Purple]b3[/color]
[color=Blue]symbol [/color][color=Purple]tempmotorspeed   [/color][color=DarkCyan]= [/color][color=Purple]b4[/color]
[color=Green]'
'      Misc Constants[/color]
[color=Blue]Symbol False            [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]Symbol True             [/color][color=DarkCyan]= [/color][color=Navy]1[/color]
[color=Green]'
'      Timer Constants[/color]
[color=Blue]Symbol mskBGTimer       [/color][color=DarkCyan]= [/color][color=Navy]%10000000 [/color][color=Green]'When only the timer is running (normally would have hInt0 & 1 config as well)[/color]
[color=Blue]Symbol flgBGTimer       [/color][color=DarkCyan]= [/color][color=Navy]%10000000 [/color][color=Green]'When only the timer is running (normally would have hInt0 & 1 config as well)[/color]
[color=Blue]Symbol tmrIntOn1stTick  [/color][color=DarkCyan]= [/color][color=Navy]65535     [/color][color=Green]'Interrupt to be caused by roll over on first major tick[/color]
[color=Blue]Symbol tmr10mS_16        [/color][color=DarkCyan]= [/color][color=Navy]64911     [/color][color=Green]'= 65536 - (Treq * 1,000,000 / Clk / 256)
'Symbol tmr100mS_8x4     = 62411     '= 65536 - (Treq * 1,000,000 / Clk / 256)
                                    ' Where: Treq = Required Time in microseconds; Clk = 16,000,000.
'[/color]
[color=Black]Init: [/color][color=Blue]let [/color][color=Purple]dirsa[/color][color=DarkCyan]=[/color][color=Navy]%11111111
      [/color][color=Blue]let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1
      [/color][color=Blue]let [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]1
      [/color][color=Blue]let [/color][color=Purple]motorspeed[/color][color=DarkCyan]=[/color][color=Navy]1
      [/color][color=Blue]let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed
      [/color][color=Blue]setfreq m16
      [/color][color=Green]'
      'Start the background timer (runs continuously)
      [/color][color=Purple]TOFlag [/color][color=DarkCyan]= [/color][color=Blue]False
      [/color][color=Purple]Timer [/color][color=DarkCyan]= [/color][color=Blue]tmrIntOn1stTick             [/color][color=Green]'
      [/color][color=Blue]SetTimer tmr10mS_16                 [/color][color=Green]'Expires after (every) 100 milliseconds
      [/color][color=Blue]SetIntFlags flgBGTimer[/color][color=Black], [/color][color=Blue]mskBGTimer  [/color][color=Green]'Set timer 0 to interrupt
      '
      ' **** Main Loop ****
      [/color][color=Blue]do
         [/color][color=Green];let direc=1
         ;pause 2000
         ;let direc=0
         ;pause 2000
      [/color][color=Blue]loop  

 
Interrupt:  High oYellowLED
            If [/color][color=Purple]tempmotorspeed [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
               dec [/color][color=Purple]tempmotorspeed
            [/color][color=Blue]Else
               let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed
               [/color][color=Blue]if [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
                  inc [/color][color=Purple]posrotor
                  [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8 [/color][color=Blue]then
                     let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1
                  [/color][color=Blue]endif 
               else
               dec [/color][color=Purple]posrotor
               [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
                  let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8
                  [/color][color=Blue]endif
               endif
               lookup [/color][color=Purple]posrotor[/color][color=Black],[/color][color=Blue]([/color][color=Navy]0[/color][color=Black],[/color][color=Navy]%00000011[/color][color=Black],[/color][color=Navy]%00000010[/color][color=Black],[/color][color=Navy]%00000110[/color][color=Black],[/color][color=Navy]%00000100[/color][color=Black],[/color][color=Navy]%00001100[/color][color=Black],[/color][color=Navy]%00001000[/color][color=Black],[/color][color=Navy]%00001001[/color][color=Blue])[/color][color=Black],[/color][color=Purple]outbyte
               pinsa[/color][color=DarkCyan]=[/color][color=Purple]outbyte
            [/color][color=Blue]EndIf[/color]
[color=Black]Int_Enable: [/color][color=Purple]TOFlag [/color][color=DarkCyan]= [/color][color=Blue]False                            [/color][color=Green]'Clear the flag
            [/color][color=Purple]Timer [/color][color=DarkCyan]= [/color][color=Blue]tmrIntOn1stTick                   [/color][color=Green]'Reset the timer
            [/color][color=Blue]SetIntFlags flgBGTimer[/color][color=Black], [/color][color=Blue]mskBGTimer        [/color][color=Green]'Set timer 0 to interrupt
            [/color][color=Blue]Low oYellowLED
            return [/color]
It can easily manage a 10mS timer interrupt. The interrupt routine exits within 3mS, so leaves some time to do other things in the main loop. Not a lot of time, but some :).
 

stan74

Senior Member
Ok. Nice one Inglwoodpete,your code works much the same as mine when I set timer to 65534 or 5,next tick is overflow,triggers interrupt and resets interrupt,interrupt re-enables itself..correct? or is this where I'm going wrong?
Anyway,please watch the bit pattern leds visibly flashing with your code pasted.If your yellow led was added, it would be flashing.If they flash every 20mS or faster, they would appear fully on so they are not flashing every 10 mS. Please ignore the other youtube carp.
flash
 

Technical

Technical Support
Staff member
interrupt re-enables itself..correct? or is this where I'm going wrong?
yes, that is where you are going wrong.

You must re-enable the interrupt every time as hippy suggested above (ie another setint before the return). In post 25 you have an extra, unwanted, return before interrupt_Enable:. This prevent the interrupt being re-enabled.


http://www.picaxe.com/BASIC-Commands/Interrupts-and-Multi-Tasking/setint/

2) When the interrupt occurs, the interrupt is then disabled and does not automatically re-enable. Therefore to re-enable the interrupt (if desired) when the interrupt processing is finished another SETINT command must be used within the interrupt sub-procedure itself. This interrupt will not be enabled until the interrupt sub-procedure's 'return' command is executed.
 

stan74

Senior Member
True Technical, I didn't notice. An hour head scratching and I went code blind. set timer 65535 scopes at 1.8 odd KHz, 20 odd % duty. It's not a myth anymore. On a 16f84 I could get interrupt dual software pwm working and the robot code on the pic. I don't think I'll need it for a stepper driven robot because the core has enough momentum that you don't notice it being off for 20 mS.
Again, thanks all. I'll post a video of the robot in the robot forum when it's finished.How do other people code stepper motor robots? Googleing picaxe interrupt unipolar stepper motor shows little.
 

stan74

Senior Member
I didn't see the mistake
Code:
[color=Blue]Interrupt:
if [/color][color=Purple]tempmotorspeed [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
      dec [/color][color=Purple]tempmotorspeed[/color]
[color=Blue]else
      let [/color][color=Purple]tempmotorspeed[/color][color=DarkCyan]=[/color][color=Purple]motorspeed
      [/color][color=Blue]if [/color][color=Purple]direc[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
            inc [/color][color=Purple]posrotor
            [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]8 [/color][color=Blue]then
                  let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]1
            [/color][color=Blue]endif 
      else
            dec [/color][color=Purple]posrotor
            [/color][color=Blue]if [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]0 [/color][color=Blue]then
                  let [/color][color=Purple]posrotor[/color][color=DarkCyan]=[/color][color=Navy]7
            [/color][color=Blue]endif
      endif
endif

lookup [/color][color=Purple]posrotor[/color][color=Black],[/color][color=Blue]([/color][color=Navy]0[/color][color=Black],[/color][color=Navy]%00000011[/color][color=Black],[/color][color=Navy]%00000010[/color][color=Black],[/color][color=Navy]%00000110[/color][color=Black],[/color][color=Navy]%00000100[/color][color=Black],[/color][color=Navy]%00001100[/color][color=Black],[/color][color=Navy]%00001000[/color][color=Black],[/color][color=Navy]%00001001[/color][color=Blue])[/color][color=Black],[/color][color=Purple]outbyte
pinsa[/color][color=DarkCyan]=[/color][color=Purple]outbyte[/color]
if posrotor=8 then let posrotor=1. Shows if one cycle is wrong the motor still runs.Making it 7 and you don't see the difference.
set timer 65300 is a tidy value,the motor pins are 37Hz so maybe enough time to do the main program will see.can't be ***** to do more sums.If I was a fisherman I'd have a haddock :)
 

lbenson

Senior Member
If I was a fisherman I'd have a haddock :)
As a resident of Nova Scotia, I've experienced haddock as a nice, white-fleshed fish, the local choice for fish and chips. But I don't understand the perhaps local UK expression, which means ???
 

inglewoodpete

Senior Member
Ok. Nice one Inglwoodpete,your code works much the same as mine when I set timer to 65534 or 5,next tick is overflow,triggers interrupt and resets interrupt,interrupt re-enables itself..correct? or is this where I'm going wrong?
Anyway,please watch the bit pattern leds visibly flashing with your code pasted.If your yellow led was added, it would be flashing.If they flash every 20mS or faster, they would appear fully on so they are not flashing every 10 mS. Please ignore the other youtube carp.
flash
The code within my interrupt routine re-enables the interrupt for the next timer expiry. I think yours does too. My code should result in a "solid" yellow LED. It's flashing at 100Hz, so the light will appear steady to us mortals. I can see flashing on the you-tube video but I'm can't tell if this is visible to a person looking at the LEDs or is it a function of the movie camera's shutter synch?

Anyway, is the simulator interrupt still "100 times faster" than my code? It shouldn't be.
 

stan74

Senior Member
Hi Pete. Haddock-Headache. The leds flash at 38Hz with set timer 65300, slower with your value. The simulator stopped working when simulating the code,displayed unexpected stopped working and pe closed.
Motor stops and doesn't start again if I use pause.
do
let direc=1 ; motor turns 2/3 revolution clockwise...turns more this direction.
for w6=1 to 1000:next w6 ;takes 4 seconds
let direc=0 ; motor turns 1/3 revolution anticlockwise
for w6=1 to 1000:next w6
loop
Parts of the interrupt run faster..inc dec ??
 
Top