Calling all PICAXE/Liberty BASIC Users!

Grant Fleming

Senior Member
I have been trying to receive a number from the PICAXE 40X1 into my PC using com port and a Liberty BASIC programme I am writing.
As a test - the number is received ok using the Prog Ed terminal, (I am not using CR or LF).
I want to read and assign a variable in Liberty BASIC to this received number from the PICAXE - I am just getting zero displayed all the time. Is this my confusion over strings, number/variables?
I am successful with sending from PC to PICAXE.

Code:
'PICAXE code:
talk:
wait 2
readadc10 0,w1  'read potentiomter into PICAXE
w2 = w1/10
sertxd (#w2)   'send pot. reading to LibertyBASIC prog (no cr,lf)
wait 2

serrxd [1000, timeout],b1     'receive user commands from LibertyBASIC 

choose:       'choose an action to operate relays  
if b1 = 0 then open 
if b1 = 1 then close
if b1 = 2 then still
goto talk

open:         'open valve 
high 3
low 4
goto talk

close:        'close valve
low 3
high 4
goto talk

still:        'stop valve 
low 3
low 4
goto talk

timeout:
goto talk



'Liberty BASIC code (partial only):

 [readvvpos]
open "COM3:4800,N,8,1,cs0,ds0,rs" for random as #comm

[repeat]
timer 50, [delay]
wait
[delay]
timer 0
dataRead$ = input$(#comm, lof(#comm))
if dataRead$ = "" goto [repeat]

close #comm

print dataRead$  ' here is where I am fumbling around (for hours)! 
dataRead$ = b$
print val(b$)
I have done many searches on this forum (found some useful snippets of code) and Liberty BASIC forum, but not finding exactly what I need.

Cheers,
Grant
 

hippy

Ex-Staff (retired)
First step - Cut the code in both the PICAXE and PC back to the bare minimum. There's just too much going on to do debugging here. On the PICAXE ...

Code:
Do
  SerTxd( "123" )
  Wait 2
Loop
I've never used Liberty Basic but from gut instincts after years of programming, I'd try ...

Code:
comm = 1
open "COM3:4800,N,8,1,cs0,ds0,rs" for random as #comm
[repeat]
if lof(#comm) = 0 Goto [repeat]
print ">"+input$(#comm,lof(#comm))+"<" 
Goto [repeat]
 

kym

Member
Grant

First try with Com1.
next you have this line back to front

dataRead$ = b$ , should be

b$ = dataRead$

and you may have to print to a Textbox like this.

dataRead$ = input$(#comm, lof(#comm))
Print #main.textbox1,dataRead$;

then leave out the repeat and delay sections until
you get this part working.


Kym
 

broonsontour

New Member
code

this code displays bytes sent computer ,in new window. u will need to change baud,com port,ect. try searching liberty basic forums. very helpfull,just noticed,
scan
needs to be added after the line:
while lof(#comhandlea)=0
as it is dificult to close the window if there are no bytes recieved.
 

Attachments

Last edited:

Grant Fleming

Senior Member
I think we're almost there!

Thanks all for the quick replies.

I have held back responding until I tried all the advice. Mostly the number I'm trying to retrieve is two digits and alot of the time I only receive the first or last.

Hippy: Your programme does the job if looping continuously like this but when I use your snippet in a bigger programme without looping I just get one digit sometimes.

Kym: Yes, I changed to b$ = dataRead$ and works now but mostly displaying one digit in my textbox.

broonsontour: A tidy little programme but always displaying only one digit.

boriz: I have always used com3 for all my succesful programmes - why would another com port make a difference?

It seems as though the 'read' operation is too quick or I have to ask specifically to look for two digits (I have searched forums again and help files but finding it tough).

Cheers,
Grant
 

moxhamj

New Member
I've got this working in vb.net (after a *lot* of work) and vb.net is free.

Start simple - solder pin 2 and 3 of a D9 plug to make a loopback tester and leave the picaxe out for the moment. Try sending out "Hello" and see if you can get it back.

In vb.net you open a port and you can then clear the buffer and send out the data. But as soon as the port was opened it is also ready to receive. So if you wait half a sec the data comes back. It doesn't get corrupted with previous reads as the buffer was cleared.

I don't know about other versions of basic, but if you are sometimes getting one byte and sometimes another, it suggests a timing issue. If you open a file for output and send some data and the receiver sends it back immediately (eg a loopback or a very fast picaxe) then you will miss the data coming back. At the very least try a pause on the picaxe before sending back.
 

hippy

Ex-Staff (retired)
Your programme does the job if looping continuously like this but when I use your snippet in a bigger programme without looping I just get one digit sometimes.
It could be that Liberty Basic is not be buffering all bytes received or loses bytes if it's busy doing something else.

If you're getting all the characters expected, but only one at a time that will be down to how the program reads what it has. The "=input$(#comm,lof(#comm))" will read however many bytes there are in the buffer at the time of execution. If the read happens in the middle of data being sent those received so far will be grabbed, the rest will show up later as a different chunk. You either need to not do an input$() until there are however many bytes you want in the buffer then only read that many, or add your own secondary buffering ...

Code:
  if lof(#comm) >= 3 then
    dataRead$ = input$(#comm,3)
  end if
or

Code:
  rxBuffer$ = rxBuffer$ + input$(#comm,lof(#comm))
  if len(rxBuffer$) >= 3 then
    dataRead$ = left$(rxBuffer$,3)
    rxBuffer$ = right$(rxBuffer$,len(rxBuffer$)-3)
  end if
The second is usually more preferable because it maximises the amount of background buffering and lowers the risk of data being lost between reads of the buffer.

For VB and other event driven programming models, the interrupt on serial data received would normally append the rxBuffer$, the main program thread would then deal only with rxBuffer$, that is, the above would be split into two halves, each running in its own thread.
 
Last edited:

jodicalhon

New Member
I'm using JustBasic, but as it's related, this may help.

Code:
open "COM3:4800, n, 8, 1, cs0, ds0, rs" for random as #comm

[main.inputLoop]
dataRead$ = input$(#comm, lof(#comm))
if dataRead$ <> "" then print #main.textedit, dataRead$;
scan
goto [main.inputLoop]
You'll obviously have to adapt it to your situation.

I've set up a text entry box and a button to send the text out of the com port.
I also have a text edit box to display any received text.
My cable has its output connected back to the input, so that anything sent is immediately sent back.

I've just sent, and received without errors:
"The quick brown fox jumped over the lazy dogs."

Hope it helps.

p.s. You should be able to drop your timer command.

p.p.s Here's the code for when the SEND button is clicked:
Code:
[buttonSENDClick]
print #main.textboxSEND, "!contents? aString$"
print #comm, aString$
goto [main.inputLoop]
 
Last edited:

Grant Fleming

Senior Member
Success! (With a little help from my friends).

Well, 'timing is critical' - I seem to remember reading that before in this forum!

Hippy: Yes, if my PICAXE programme was off doing something else and not quite back in time for the sending then I didn't always grab the whole message. Found that also if I kept the comport open for longer than it needed to be this happened.
Now I have the PICAXE just waiting with serrxd until Liberty BASIC sends a prompt to tell PICAXE to send the numbers. Liberty waits for this with the timer setting (had to play around with this).

Dr Acula: My aim was not to send to PICAXE and return same data (although this may just be my next project)! I was simply wanting to receive from PICAXE into Liberty. I see where you are coming from though. I was always ok with loopback tests (have a couple of small test programmes that I use) and this is what had be stumped, loopback test was fine but then testing with PICAXE sending to Liberty was not always successful. Because of this it got me focused on timing issues as you mentioned.

Jo C: As mentioned above, loopback is fine with the right programmes but I am having PICAXE talking.

Thanks all for all your suggestions and code.

Here is my working pieces of code for both PICAXE and Liberty BASIC:

PICAXE code:
Code:
'Serial comms with Liberty BASIC - sending numbers to be displayed in PC window


talk:
pause 250      'let things start-up
readadc10 0,w1 'read potentiomter into PICAXE
w2 = w1/10     '1K pot reading resolution came close enough to a 0 to 100% when dividing by 10 
sertxd (#w2)   'send pot. reading to LibertyBASIC prog (no cr,lf)


     
listen:                   'receive user commands from LibertyBASIC 
serrxd b1                 'I'll wait here for as long as it takes until I hear something!
if b1 = 1 then goto talk  'if PC prompts me and asks me the right question I will read and talk
goto listen               'if not I'll go back to listening


Liberty BASIC code:
Code:
 'PICAXE - Serial Comms - reading numbers from a PICAXE and displaying in window

[openport]
open "Com3:4800,n,8,1,ds0,cs0,rs" for random as #comm  '(COM3 is all set-up on my PC, it works, baud of 4800 suits PICAXE)

[request] ' To request/prompt PICAXE to read ADC & send to PC - this needed to synchronise the exchange
print #comm,Chr$(1); '"Print" sends the bytes, Chr$ takes care of converting the number to the code equivalent.
   'Adding a semicolon stops the print command from sending the Carriage Return and Line Feed characters at the end of the printing-
   '(which would confuse the PICAXE).

[timer]
EndTime = time$("ms") + 1750 'Time (in msec) adjusted to give enough time for PICAXE to send AND enough time for PC to receive
while time$("ms") < EndTime
wend

[listen]
if lof(#comm) = 0 Goto [request] 'if not hearing anything ask again if PICAXE will read ADC and tell PC about it -(thanks Hippy)
dataRead$ = input$(#comm, lof(#comm)) 'read what PICAXE has to offer

[closeport]
Close #comm           'close COM3 as soon as possible - (found if closed later strange things received)!

[display]
print dataRead$   ' print the latest potentiometer feedback reading to PC window - mission accomplished!
Cheers,
Grant
 

jodicalhon

New Member
Dr Acula: My aim was not to send to PICAXE and return same data (although this may just be my next project)! I was simply wanting to receive from PICAXE into Liberty. I see where you are coming from though. I was always ok with loopback tests (have a couple of small test programmes that I use) and this is what had be stumped, loopback test was fine but then testing with PICAXE sending to Liberty was not always successful. Because of this it got me focused on timing issues as you mentioned.

Jo C: As mentioned above, loopback is fine with the right programmes but I am having PICAXE talking.
No worries, Grant, glad you got it up and working.

But for future info, the code I posted works fine for PC to picaxe comms as well.

Here's my picaxe test code:
Code:
main:
serin 4, N2400, b1

if b1 = "1" then gosub light
if b1 = "2" then gosub fox

goto main

light:
readadc 2, b0
serout 0, N2400, (#b0)
return

fox:
serout 0, N2400, ("The quick brown fox jumped over the lazy dogs.")
return
With the JB code I posted, with suitable baud, etc, this works a treat. No timer needed on the PC side. Receipt on the PC end has been glitch free.

I had what I assume are similar problems to yours coding a robot head controller. After much head scratching and testing, I found this easy solution. I think it's the scan wot does it.

A while back, Tarzan posted the JustBasic code for a 4x4 controller. He had some issues with data receipt and went for a timer, too. My code fixes the problems in his controller as well.
 

rbright

Member
Grant I'd Like To See Your Project Develop....

Grant, I'd like to see how your project/s develop over time. Some time back I was playing around with LB making a GUI for a PIXAXE, just for the exercise and found similar problems that you have experienced. Keep at it.
 

hippy

Ex-Staff (retired)
' close COM3 as soon as possible - (found if closed later strange things received)!
There's something odd going on there then as it should be okay to open the COM port at the start of the program and keep it open until the application ends.

If I were in this position I'd want to know why strange things were being received. Hopefully it's just something the PICAXE is being instructed to put out which makes no sense to the program or a coding error in your source but if the PICAXE isn't sending data and Liberty Basic is receiving garbage I'd want to know how and why.

Closing and re-opening is a hack, kludge, bodge, workaround, dodge, fudge ( select a term to match ethnicity ) and that might not be possible to use in other situations. If I couldn't get Liberty Basic working reliably in this simple case I wouldn't be confident in getting it to work in more complicated cases.
 

Grant Fleming

Senior Member
Actually I can close comport later!

Hippy: I have now closed comport last - all is well!
I blamed 'strange things' (not receiving all the data) before on the time of closing of the com port - this not the reason.
Now it seems that the 'prompt' sent to tell PICAXE to send and also PICAXE waiting continuously here with serrxd, plus the Liberty BASIC timer routine all synchronise the timing. Probably not all of these things needed but it works for me at the moment.
I'm sure at a later stage it will become clear to me the minimum code needed and why it works!

Below is Liberty code with 'close comm' port at the end, (the PICAXE code remains unchanged).
Code:
'PICAXE - Serial Comms - reading numbers from a PICAXE and displaying in Liberty BASIC programme window

[openport]
open "Com3:4800,n,8,1,ds0,cs0,rs" for random as #comm  '(COM3 is all set-up on my PC, it works, baud of 4800 suits PICAXE)

[request] ' To request/prompt PICAXE to read ADC & send to PC - this needed to synchronise the exchange
print #comm,Chr$(1); '"Print" sends the bytes, Chr$ takes care of converting the number to the code equivalent.
   'Adding a semicolon stops the print command from sending the Carriage Return and Line Feed characters at the end of the printing-
   '(which would confuse the PICAXE).

[timer]
EndTime = time$("ms") + 1750 'Time (in msec) adjusted to give enough time for PICAXE to send AND enough time for PC to receive
while time$("ms") < EndTime
wend

[listen]
if lof(#comm) = 0 Goto [request] 'if not hearing anything ask again if PICAXE will read ADC and tell PC about it -(thanks Hippy)
dataRead$ = input$(#comm, lof(#comm)) 'read what PICAXE has to offer

[display]
print dataRead$   ' print the latest potentiometer feedback reading to PC window - mission accomplished!

[closeport]
Close #comm           'close COM3

Jo C: Thanks for your code, alot of good ideas in there. I find talking with other serial devices quite interesting and rewarding as you do.

rbright: I have a couple of Liberty BASIC GUI's for switching on and off LED's (very exciting) with the PICAXE but obviously you can switch anything with relays etc. I will post these shortly and also I can let you know of this two way serial comms project that this thread is about- a larger programme that is almost finished.
 
Top