The "hello world" of basic programming

Post here to discuss programming with swordfish basic

Moderators: Chuckt, Garth, bitfogav

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

The "hello world" of basic programming

Post by brad » Wed Jun 16, 2010 6:27 am

I have spent a number of hours with coding in basic and I can tell you, it's quite alot of fun!

Here is a quick and dirty tutorial on how to make a single LED flash on and off on PORTB pin 0.

The Circuit
First of all you will need a microcontroller. My favourite at the moment is the pic 18f4685, so I will be using that. You will also need a programmer, an LED and a resistor (pretty much anything from 120 ohm to 1kohm will do)

Connect the cathode of the LED to one end of the resistor and the other end of the resistor to ground. Then connect the other end of the LED (the anode) to PORTB pin 0. And that's the circuit!

The code
Even if you haven't ever programmed in Basic, the code here will be quite easy to recognise.

Code: Select all

Device = 18F4685         // Tell the compiler what chip we are using
Clock = 8                // Tell the compiler what we will be setting the clock to (Mhz)           
Config OSC = IRCIO67     // This tells the microcontroller to use the internal clock 

include "utils.bas"      // we are including an extra file here which allows us to use shortcuts
                         // like "SetAllDigital" Which will take care of making all ports digital ports.    

// Start Of Program...
OSCCON = %01111111                  // Sets the internal oscillator for 8Mhz
SetAllDigital                       // Make all Pins digital I/O's
TrisB = %00000000                   // Make all PORTB pins outputs (even though we only need PORTB, 0) 

// Main Loop
While True()                        // This creates an infinite loop
        PORTB.0 = 1                   // Turn the LED on
        DelayMS(500)                // Hold that for half a second
        PORTB.0 = 0                   // Turn the LED off
        DelayMS(500)                // Hold that for half a second
Wend                                // Loop back to the while loop as long as we havent finished.
Everything in the code above is quite straight forward. A key thing to note is that the "CLOCK =" setting and the actual setting that you configure the microcontroller clock to must be the same, otherwise your timings will be all out when we get to DelayMS(500) because the compiler is automatically configuring it to delay for half a sec BASED ON THE CLOCK SPEED YOU TOLD IT YOU WERE RUNNING AT.

the % symbol before digits means that we are using binary.

The While Wend loop is very handy indeed! Basically we will remain in the loop the whole time our While statement is true (in the example above it will never be false because I have set it to true.

Here's a better example. Lets say I only wanted the LED to flash on then off 10 times and then stop. Here's the While Wend code:

Code: Select all

dim counter as byte

counter = 10

While counter > 0                        // This will loop as long as counter is greater than 0
        PORTB.0 = 1                   // Turn the LED on
        DelayMS(500)                // Hold that for half a second
        PORTB.0 = 0                   // Turn the LED off
        DelayMS(500)                // Hold that for half a second
        Dec(counter)                 // take one away from the counter variable
Wend                                // Loop back to the while loop as long as we havent finished.
So you can see above that we now declare a variable (counter) and we set it up with the decimal number 10. So when we come to the While statement, it is going to be true (10 is greater than 0) so we run the code below it.

The code will turn the led on, hold then turn it off and hold. it will then take one away from our counter (which now leaves 9) and will go back to the while statment. It checks if the statement is true (which it is, 9 is greater than 0)

It will keep doing this until our counter variable is not greater than 0.
Last edited by brad on Sun Jul 25, 2010 8:39 pm, edited 2 times in total.

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sat Jul 24, 2010 11:48 pm

Hey Brad, Ive been experimenting with this pic basic using swordfish, Ive followed all your description above using a 18F4550, but at first I could'nt get it to work :? so I changed one of your lines from

While counter > 0()

To =

While counter >(0)

so the LED would flash 10 times, and now it works!! :) is this line correct? well it seems to work :) hehe!

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sun Jul 25, 2010 12:07 am

Heres the pic basic code that I have been playing with, Flashes a LED connected on PORTB,0 10 times and then flashes a LED connected to PORTA,0 forever!! hehe! :)

The hardest part I found was knowing how to config the Internal Oscillator.

Code: Select all

Device = 18F4550

Clock = 8

Config FOSC = INTOSCIO_EC


Include "utils.bas" 

Dim LED As PORTA.0                  // Assign an alias for "LED" 
Dim LED2 As PORTB.0                  // Assign an alias for "LED" 


dim counter as byte                 // assigns a Byte to counter

// Start Of Program...
OSCCON = %01111111                  // Sets up the internal oscillator
SetAllDigital                       // Make all Pins digital I/O's
Low(LED)                            // Make the LED pin an output and set it low 
Low(LED2)                           // Make the LED pin an output and set it low


counter = 10 
    
While counter >(0)                   // This creates an infinite loop 
        LED2 = 1                     // Turn the LED on 
        DelayMS(500)                 // Hold that for half a second 
        LED2 = 0                     // Turn the LED off 
        DelayMS(500)                 // Hold that for half a second 
        Dec(counter)                 // Decrement our counter
 
Wend
    
        
While True     

    LED = 1                         // Turn on the LED     
    DelayMS(500)                    // Delay for half a second    
    LED = 0                         // Turn off the LED   
    DelayMS(500)                    // Delay for half a second 
    
Wend

Mitchy
decided to stick around...
decided to stick around...
Posts: 30
Joined: Sun Jul 04, 2010 10:44 am
Location: Australia
Contact:

Post by Mitchy » Sun Jul 25, 2010 10:37 am

Hi bitfogav,
The hardest part I found was knowing how to config the Internal Oscillator.
AndyO from Digital DIY created a Swordfish User Module called "InternallOscillator.bas" which configures the internal oscillator depending on the settings you have chosen. I've expanded the module over time to include support for other popular PICs

Here's an example of how you would use it:

Code: Select all

Device = 18F4550
Clock = 32

Include "InternalOscillator.bas"

// main program...
While True
    Toggle(PORTB.0)
    DelaymS(500)
Wend
Clock = 32 could be changed to any of the PICs configurable speeds (31Khz through to 32Mhz)

You can find the user module along with other handy ones in the Digital DIY Swordfish User Module Pack. The pack is updated regularly, so be sure to drop by for updates (and post requests if need be!)

InternalOscillator.bas supported devices as of 25th July 2010:

Code: Select all

*          : Supported devices: 18F1220, 18F1320, 18F2420, 18F2520, 18F4420,   *
*          : 18F4520, 18F2455, 18F2550, 18F4455, 18F4550, 18F2620, 18F4685     *
*          : 18F25K20, 18F45K20                                                *

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sun Jul 25, 2010 8:07 pm

Hi, Mitchy

Thanks for all that help with the internal oscillator, I have been using assembly language for quite awhile now, and just started using swordfish and basic language, so it is all new to me. I am just picking it up as I go along.

I didnt even know that there was a user module pack that you could download from digital diy :) thanks for that..

Just one other thing? how do you setup things like power on timer, watchdog timer etc? or is that all taken care of with the swordfish user internal osc module?

:)

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sun Jul 25, 2010 8:31 pm

I have now Downloaded the user modules to swordfish and tried to compile this code, but it comes up with this

#error "Can not configure OSCCON for chosen clock speed"

Am I doing something wrong?

Code: Select all

Device = 18F4550 
Clock = 32

Include "InternalOscillator.bas" 

// main program... 
While True 
    Toggle(PORTB.0) 
    DelayMS(500) 
Wend
But if I change it to this then it works fine

Code: Select all

Device = 18F4550 
Clock = 8

Include "InternalOscillator.bas" 

// main program... 
While True 
    Toggle(PORTB.0) 
    DelayMS(500) 
Wend

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Sun Jul 25, 2010 8:42 pm

bitfogav wrote:Hey Brad, Ive been experimenting with this pic basic using swordfish, Ive followed all your description above using a 18F4550, but at first I could'nt get it to work :? so I changed one of your lines from

While counter > 0()

To =

While counter >(0)

so the LED would flash 10 times, and now it works!! :) is this line correct? well it seems to work :) hehe!
Really sorry - my mistake!

you don't need parenthesis at all, all you need to write is:

Code: Select all

While counter > 0
Sorry about that :oops:

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Sun Jul 25, 2010 8:45 pm

bitfogav wrote:I have now Downloaded the user modules to swordfish and tried to compile this code, but it comes up with this

#error "Can not configure OSCCON for chosen clock speed"

Am I doing something wrong?

Code: Select all

Device = 18F4550 
Clock = 32

Include "InternalOscillator.bas" 

// main program... 
While True 
    Toggle(PORTB.0) 
    DelayMS(500) 
Wend
But if I change it to this then it works fine

Code: Select all

Device = 18F4550 
Clock = 8

Include "InternalOscillator.bas" 

// main program... 
While True 
    Toggle(PORTB.0) 
    DelayMS(500) 
Wend
The 18f4550 supports upto a 48Mhz clock via an external oscillator but unfortunately the internal clock can only do upto 8Mhz

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sun Jul 25, 2010 8:49 pm

haha this is like a whole new world to me!! :D

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Sun Jul 25, 2010 8:51 pm

bitfogav wrote:haha this is like a whole new world to me!! :D
good fun isn't it!

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sun Jul 25, 2010 8:54 pm

brad wrote:
bitfogav wrote:haha this is like a whole new world to me!! :D
good fun isn't it!

Yes surprising how easy it is, just s few lines can do alot :D

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Sun Jul 25, 2010 9:38 pm

UPDATE! I had an error in my code but has now been fixed. I needed to change:

Code: Select all

Sub debounce_buttons()
    If button_debounce <> 0 Then
        Dec(button_delay)
    EndIf
End Sub
to:

Code: Select all

Sub debounce_buttons()
    If button_delay <> 0 Then
        Dec(button_delay)
    EndIf
End Sub
AND NOW BACK TO THE ORIGINAL POST...


Here's another tid bit just to take things further with some select case statements.

Lets say we had one led that we wanted to flash and we also wanted to vary the speed at which it flashes. We would connect two push buttons to our microcontroller (one to increase the speed and one to decrease)

PLEASE NOTE! I have not tested this code, I just wrote it up and it looks like it will work okay but if you try it and it doesn't work then just let me know and I'll fix it up :)

Here's the code:

Code: Select all

Dim x As Byte
Dim flash_speed As Byte
Dim button_delay As Byte

Dim led As PORTA.0
Dim inc_button As PORTB.1
Dim dec_button As PORTB.2

Sub flash_led()
    For x = 0 To 1
        Toggle(led)
        Select flash_speed
            Case 0
                DelayMS(100)
            Case 1
                DelayMS(300)
            Case 2
                DelayMS(500)
            Case 3
                DelayMS(700)
            Case 4
                DelayMS(1000)
        End Select
    Next  
End Sub


Sub check_buttons()
    If button_delay = 0 and inc_button = 1 and flash_speed < 4 then
        inc(flash_speed)
        button_delay = 50
    elseif button_delay = 0 and dec_button = 1 and flash_speed > 0 then
        dec(flash_speed)
        button_delay = 50
    endif
End Sub


Sub debounce_buttons()
    If button_delay <> 0 Then
        Dec(button_delay)
    EndIf
End Sub


While true
    flash_led
    check_buttons
    debounce_buttons
Wend
Anyway, you can see that there are three routines that we call. One takes care of flashing the led, one takes care of checking the push buttons and the last one takes care of ensuring that we have a delay between accepting buttons presses.

The select case statements are a little bit like having alot of if then statements but is a little more efficient. I think it is quite self explanatory but as always, post here if you are unsure.

Now this is where the beauty of basic comes in! you can have so many variables in one line of code! The line I am referring to is in the check button sub routine.

We will only run what is after the 'then' statement if three things turn out to be true. We need the delay to be 0 AND we need to actually be pressing the button AND we need to be at a number less than 4. (we don't want to go past 4 because I have only setup enough select case statements to go from 0 to 4)

So all in all, it flashes the LED at five different speeds which is determined by the up / down buttons.
Last edited by brad on Mon Jul 26, 2010 6:10 am, edited 2 times in total.

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Sun Jul 25, 2010 10:49 pm

wow that is cool, I have tried it out but ive added the line

Dim button_debounce As Byte

but swordfish says there still a few errors in it :?


Image[/list]
Attachments
sf.jpg
sf.jpg (72.53 KiB) Viewed 11115 times

User avatar
bitfogav
Moderator
Moderator
Posts: 908
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Post by bitfogav » Mon Jul 26, 2010 4:39 am

I think ive Cracked it!!! :D

heres a working and tested version of your basic language code above, notice that I had to remove part of the code button_delay = 0 as for some reason this was stopping it working :? and ive changed a few things. :)

Code: Select all

Device = 18F4550 
Clock = 8

Include "InternalOscillator.bas" 
Include "utils.bas"

Dim x As Byte 
Dim flash_speed As Byte
Dim button_delay As Byte
Dim led As PORTA.0 
Dim inc_button As PORTB.1 
Dim dec_button As PORTB.2 

    // Flash LED on RA0
Sub flash_led() 
    For x = 0 To 1 
        Toggle(led) 
        Select flash_speed 
            Case 0 
                DelayMS(100) 
            Case 1 
                DelayMS(300) 
            Case 2 
                DelayMS(500) 
            Case 3 
                DelayMS(700) 
            Case 4 
                DelayMS(1000) 
        End Select 
    Next  
End Sub 

    // check buttons  - buttons have pull-up resistors connected to 5v
Sub check_buttons() 
    If  inc_button = 0 And flash_speed < 4 Then  ' increases flash speed
        Inc(flash_speed) 
        button_delay = 50 
    ElseIf 
        dec_button = 0 And flash_speed > 0 Then  ' decreases flash speed
        Dec(flash_speed) 
        button_delay = 50 
    EndIf 
End Sub 
  
    // Make all Pins digital I/O's 
SetAllDigital                       
TRISA = %00000000
TRISB = %11111111

flash_speed = 0    ' changing this number will change the start speed of the led

   //  prog starts here
While true 
    flash_led 
    check_buttons 
Wend 

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Mon Jul 26, 2010 6:15 am

bitfogav wrote:wow that is cool, I have tried it out but ive added the line

Dim button_debounce As Byte

but swordfish says there still a few errors in it :?
Sorry about that, I was using the incorrect variable name, check my post above with the big red font to see my correction :oops:

Those errors are more just warnings. They are simply saying that I have some declared variables but I am not initially setting them to a designated value. Once again this is just me being lazy and not giving a complete piece of code to finish the job.

Now the reason that it worked for you when you took out that extra and statement about the button_delay is because of my previous error.

What is supposed to happen is that you press the button, it loads up a variable with the number 50. then it wont let you press a button again untill that variable has gone all the way back to 0 again. but because I was using the incorrect variable name, I was never actually decrementing this variable which therefor meant it would never get to 0 and you could never inc or dec the speed.

so if you ow use the above fixed code, it should work much better :D

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest