Swordfish L O n G delay

Status
Not open for further replies.

MrDEB

Well-Known Member
Built a BAT Repellent that I want to output every 20 minutes for 10 miniutes then shut off output for 20 minutes then back on.
I understand that using DELAYMS for really long delays is not the best method.
I have this code but is there a better method?
Code:
Device = 18F1320
Clock = 8

Include "ISRTimer.bas"

// constant ID to 4 * 16 bit timers...
Const
Timer1 = 0,
Timer2 = 1,
Timer3 = 2,
Timer4 = 3

// OnTimer1 event...
Event OnTimer1()
Toggle(PORTB.0)//pin 8
End Event

// OnTimer2 event...
Event OnTimer2()
Toggle(PORTB.1)//pin9
End Event

// OnTimer3 event...
Event OnTimer3()
Toggle(PORTB.2)//pin 17
End Event

// activate the timer module...
Timer.Initialize

// initialise the timers - refresh every 1000Hz (1ms)...
Timer.Items(Timer1).Interval = 50 // 50ms
Timer.Items(Timer1).OnTimer = OnTimer1 // timer event handler
Timer.Items(Timer2).Interval = 250 // 250ms
Timer.Items(Timer2).OnTimer = OnTimer2 // timer event handler
Timer.Items(Timer3).Interval = 500 // 500ms
Timer.Items(Timer3).OnTimer = OnTimer3 // timer event handler
Timer.Items(Timer4).Interval =2000 // 2000ms, no event handler

// enable the timers...
Timer.Items(Timer1).Enabled = true
Timer.Items(Timer2).Enabled = true
Timer.Items(Timer3).Enabled = true
Timer.Items(Timer4).Enabled = true

// start processing all timers...
Timer.Start

// main program loop...
While true
// this is a polled timer, not event driven - check to see
// if it has timeout...
If Not Timer.Items(Timer4).Enabled Then
Toggle(PORTB.3)
Timer.Items(Timer4).Enabled = true
EndIf

// background flash LED...
High(PORTB.7)//pin 13
DelayMS(5)
Low(PORTB.7)//pin 13
DelayMS(5)
Wend
 
It depends how accurate you need it to be. One method is to connect a 32.768Khz crystal and use a timer lasting 10 or 15 seconds, adding an internal counter until you reach the delay you need. This can be very accurate if you make the adjustments (I played with this recently). It also means you can sleep between periods, which means low power.

What I would do in your situation is use one timer of a known length and count upwards until you've reached the period you need. I would consider using an interrupt routine instead to free up your main loop, but I have no idea how that works in Swordfish.

As a hint for the future, if your code works then describe (briefly) what you are doing, rather than relying on people to read code. That might speed up replies.
 
Will try that
One problem I ran into is I inserted a delay timer routine and had an error as I am already using a timer.
Accuracy-not really necessary. I just don't want the unit to run 24/7.
May just resort to several loops and put out my white flag of surrender (the cheap way out)
 
You can use an interrupt to set a flag every second.
Code:
Interrupt MyInt()
    TMR2IF=0
    Count=Count+1
    If Count=50 Then
        Count=0
        IntFlag=1
    EndIf
End Interrupt
You could then write a delay function,
Code:
Sub Delay(Seconds as Word)
Dim x as Word
    for x=0 to Seconds
        While(IntFlag=0)
        Wend
        IntFlag=0
    next
end sub
And then you main code would be
Code:
OSCCON = $72            // select 8MHz internal clock
ADCON1  = $7f           //all digital
NOT_RBPU=0              //WPUs on port B
T2CON = %01001110       //pre=16 post=10
PR2 = 249               //=8000000/4/16/10/250 = 50Hz
TMR2IE=1                //enable timer 2 interrupts
Enable(MyInt)           //set interrupt going
While true
    LED(1)              //light LED 1    
    Delay(5)            //wait 5 seconds
    LED(2)              //light LED 2
    Delay(1)            //wait 1 second
Wend

You can make the delay as long as you like up to 65535 seconds which is about 18 hours.

See attachment for a complete module.

Mike.
 

Attachments

  • LongDelay.bas
    2.4 KB · Views: 148
Thanks now to see if it coinflicts with the timer I have in the BAT CODE (part of the CRITTER RIDDER CODE)
will let you know about the results
Yo Pommie, are you familiar with a MAX6675 that uses SPI
wanting to build a temp controled soldering iron. The orginal design used a 16F88 and assembly. I strike out on both.
Want to use a 18F452 and Swordfish. Was going to use a 1320 but it has no SPI port.
 
You should probably start a new thread for that. However, SPI is an incredibly easy protocol and can be driven by software. You don't need the advanced ports to do it.

I am unsure what software support Swordfish has for it, but I would be surprised if the answer was "none".
 
your saying I can keep the 1320 instead of the 452
The 1320 has no SPI port but the 452 has several
 
Yes. It is easily possible to implement SPI (or I2C) in software on the 18F1320. I have done it for a number of devices.

I do not know what support Swordfish has for this, either wait for someone knowledgeable like Pommie or do a bit of googling to see.
 
I tried several different insertions of code into the code I am using and keep getting contemplation errors.
It conflicts with the interupt I already have.
this is getting downright frustrating.
I tried inserting a usart into code to follow the progress but can't seem to get it working.
I guess I will breadboard some LEDs then go at it again.
I inserted a DELAYMS(10000) and no errors but I need to test.
 
I kinda started all over copying n pasting from old code.
Got something right but can't figure out what?
The ENABLE (MyInt) gets it going then it stops as expected BUT to get going again I have to check the MCLR box then un-check and away it goes for predetermined number of Tones.
Is there a way to toggle MCLR or do I resort to a transistor switch?
I looked in the Swordfish reference and came up empty.
I even tried ENABLE (MyInt) again.
Figure I would just insert a long delayms as accuracy is not needed
 
Crashing?

In Pickit2 window using a Junebug I don't even need the VDD ON box checked!!??
ALL I want is to have the tone code run for say 5-10 minutes the off for 20 then on again
Code:
device = 18F1320
clock = 8 // 8MHz clock
config OSC = INTIO2, WDT = OFF, LVP = OFF

dim NOT_RBPU as INTCON2.7
dim TMR1IE as PIE1.0
dim TMR1IF as PIR1.0
dim TMR1 as TMR1L.AsWord
dim Speaker as PORTB.3// speaker output port pin 18
dim SpeakerTris as TRISB.3



//Dim PIR As PORTB.2 // turns on PIR
//Dim PIRTris As TRISB.2
dim speed as byte


//global variables


dim Seed as longword, Tone as byte
dim i as byte
    
//half period delays = clock speed divided by 2*frequency
const Tones(18) as word = (2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000,
2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000,2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000)

      
      

      
      
//interrupt routine

interrupt MyInt()
    T1CON.0=0 //stop timer
    TMR1=-Tones(Tone) //reset period
    T1CON.0=1 //restart timer
    if Tone=5 then //if silence
    Speaker=0 //speaker off
   
   
    else //otherwise
    toggle(Speaker) //make sound
    
    endif
    TMR1IF=0 //clear interrupt flag
end interrupt
function Rand(Range as byte) as byte
dim i as byte, feed as bit, temp as word
    for i = 0 to 7 //generate 8 bits
    Feed = Seed.30 xor Seed.27 //make new bit
    Seed=Seed*2+Feed //shift seed left and add new bit
    next
Temp=(Seed and 255) * Range //change Rand from 0 to 255
Rand = Temp/256 //to 0 to (Range-1)
    end function

//main code starts here

OSCCON = $72 //select 8MHz internal clock
NOT_RBPU=0 //WPUs on port B
ADCON1=$7f //all digita
TRISB.0=0               //make output
PORTB.0=1               //and high
T1CON = %10000001 //pre=1
Tone=5 //no sound please
TMR1IE=1 //enable timer 1 interrupt
enable(MyInt) //set interrupt going
    SpeakerTris=0 //Setup Port
    
    Seed=$12345678 //seed random number
    speed = 25 //changes via dip switches


    
   // If PORTB.2=0 Then 		//if PIR activated portRB2 is low
        for i = 1 to 200 	//play 20 tones
            Tone=Rand(5) 	//each tone is random frequency
            delayms(speed) 	//and for 25-200 seconds here is where I want to change
           
            
        next 			//end for loop
 // delayms(100)
  //delayms(200)
    //        Enable(MyInt) //set interrupt going 
 
       
   // Else 			//otherwise
        Tone=5 			//silence
        i=Rand(255) 		//make rand more random
   // EndIf 			//end if condition

   
   Tone=5 //silence
   i=Rand(255) //make rand more random
  // PORTB.0 = 0//to save power put to sleep
  delayms(200)// MY LATEST ATTEMPT
  TMR1IF=0 //clear interrupt flag
    enable(MyInt) //set interrupt going 
end //end of while loop
 
Not sure if doing this right??

moved WHILE TRUE STATEMENT then start interrupt
Then do a long delayms
Have yet to test (Junebug on other computer etc.)
The basic prg works but don't need porty B0 as that is for a PIR trigger,
I just need to keep recycling with ten minutes off, then play tones then off again.
at least the code is not crashing.
I was wondering if maybe a CONTINUE statement might be in order??
Code:
device = 18F1320
clock = 8 // 8MHz clock
config OSC = INTIO2, WDT = OFF, LVP = OFF


dim NOT_RBPU as INTCON2.7
dim TMR1IE as PIE1.0
dim TMR1IF as PIR1.0
dim TMR1 as TMR1L.AsWord
dim Speaker as PORTB.3
dim SpeakerTris as TRISB.3
dim de_lay as PORTB.0
//global variables
dim Seed as longword, Tone as byte
dim i as byte


//half period delays = clock speed divided by 2*frequency
const Tones(18) as word = (2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000,
2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000,2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000)

//interrupt routine
interrupt MyInt()
T1CON.0=0 //stop timer
TMR1=-Tones(Tone) //reset period
T1CON.0=1 //restart timer
if Tone=5 then //if silence
Speaker=0 //speaker off
else //otherwise
toggle(Speaker) //make sound
endif
TMR1IF=0 //clear interrupt flag
end interrupt

function Rand(Range as byte) as byte
dim i as byte, feed as bit, temp as word
for i = 0 to 7 //generate 8 bits
Feed = Seed.30 xor Seed.27 //make new bit
Seed=Seed*2+Feed //shift seed left and add new bit
next
Temp=(Seed and 255) * Range //change Rand from 0 to 255
Rand = Temp/256 //to 0 to (Range-1)
end function


//main code starts here

OSCCON = $72 //select 8MHz internal clock
NOT_RBPU=0 //WPUs on port B
ADCON1=$70 //all digital
T1CON = %10000001 //pre=1
Tone=5 //no sound please
TMR1IE=1 //enable timer 1 interrupt
 while (true)
 if de_lay = 0 then

enable(MyInt) //set interrupt going
SpeakerTris=0 //Setup Port
Seed=$12345678 //seed random number
//de_lay=0 
//while(TRUE) //repeat forever


//if de_lay=0 then //if button 1 pressed add PIR here  pin 8
//toggle (de_lay) 
for i = 1 to 200 //play 20 tones
Tone=Rand(5) //each tone is random frequency
delayms(25) //and for 1.00 seconds
next //end for loop
de_lay=1
else //otherwise if pin 8 is high
//time delay



Tone=5 //silence
i=Rand(255) //make rand more random
endif //end if condition
delayms(10000)// INSERT a long 10 minute delay here then start all over
// at WHILE TRUE

wend //end of while loop
 
You appear to be making random changes without understanding what you are doing. I suggest you find a good book on Modular Basic and have a good read.

Anyway, here is your code with a bit of tidying. It now does 5 minutes of random tones, is silent for 10 minutes and then repeats.
Code:
device = 18F1320
clock = 8 // 8MHz clock
config OSC = INTIO2, WDT = OFF, LVP = OFF

dim NOT_RBPU as INTCON2.7
dim TMR1IE as PIE1.0
dim TMR1IF as PIR1.0
dim TMR2IE as PIE1.1
dim TMR2IF as PIR1.1
dim TMR1 as TMR1L.AsWord
dim Speaker as PORTB.3// speaker output port pin 18
dim SpeakerTris as TRISB.3

//global variables
dim Seed as longword, Tone as byte
dim i as word, count as byte
dim speed as byte
dim IntFlag as bit
    
//half period delays = clock speed divided by 2*frequency
const Tones(6) as word = (2000000/12000,2000000/10000,2000000/8000,2000000/6000,2000000/4000,1000)

//interrupt routine
interrupt MyInt()
    if TMR1IF=1 then
        T1CON.0=0 //stop timer
        TMR1=-Tones(Tone) //reset period
        T1CON.0=1 //restart timer
        if Tone=5 then //if silence
            Speaker=0 //speaker off   
        else //otherwise
            toggle(Speaker) //make sound
        endif
        TMR1IF=0 //clear interrupt flag
    endif
    if TMR2IF = 1 then
        TMR2IF=0
        Count=Count+1
        If Count=50 Then
            Count=0
            IntFlag=1
        endif
    EndIf
end interrupt

Sub Delay(Seconds as Word)
Dim x as Word
    for x=0 to Seconds
        While(IntFlag=0)
        Wend
        IntFlag=0
    next
end sub

function Rand(Range as byte) as byte
dim i as byte, feed as bit, temp as word
    for i = 0 to 7 //generate 8 bits
        Feed = Seed.30 xor Seed.27 //make new bit
        Seed=Seed*2+Feed //shift seed left and add new bit
    next
    Temp=(Seed and 255) * Range //change Rand from 0 to 255
    Rand = Temp/256 //to 0 to (Range-1)
end function

//main code starts here

OSCCON = $72            //select 8MHz internal clock
NOT_RBPU=0              //WPUs on port B
ADCON1=$7f              //all digita
TRISB.0=0               //make output
PORTB.0=1               //and high
T1CON = %10000001       //pre=1
Tone=5                  //no sound please
TMR1IE=1                //enable timer 1 interrupt
T2CON = %01001110       //pre=16 post=10
PR2 = 249               //=8000000/4/16/10/250 = 50Hz
TMR2IE=1                //enable timer 2 interrupts
enable(MyInt)           //set interrupt going
SpeakerTris=0           //Setup Port    
Seed=$12345678          //seed random number
speed = 25              //changes via dip switches
    while TRUE
        for i = 1 to 5*60 	//play for 5 minutes
            while IntFlag=0
                Tone=Rand(5) 	//each tone is random frequency
                delayms(speed) 	//and for 25-200 seconds here is where I want to change
            wend
            IntFlag=0
        next 			    //end for loop
        Tone=5 			    //silence
        i=Rand(255) 		//make rand more random
        Delay(10*60)        //delay 10 minutes
    WEND
end

Take note of the indenting. It is there to help other people follow the code flow, So code between for and next is indented to show where it starts and ends. Same with While..Wend and If..Endif.

Also, the code only ever makes 5 different notes and so extending Tones() has no effect.

Mike.
 
I will give it a try.
At present, as suggested by another form, remove the interrupt as its only there for the PIR trigger
Will start using indenting. Was unaware.
As for modular basic, I have a book on PIC BASIC but it gets into something that doess not resemble Swordfish (I like Swordfish as its kinda easier to follow)
Thanks
 
I see you changed the number of TONES.??
The original code had a bunch of tones. Any reason why the removal of tones?
 
The interrupt is not for the PIR trigger. It plays the sound, no interrupt, no sound. Whoever told you otherwise is mistaken.

Mike.
 
I removed the extra tones as they were not being used. The code only uses the first 5 values and so adding more had no effect.

Mike.
 
ONLY 5 tones are used?
Then I need to figure out how to get at least 12 different random frequiencies.
Need 2-8 khz and 15-25khz
Thanks
and all this time I thought I was getting all desired frequiencies.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…