PDA

View Full Version : Scripting timing when using com ports- on robotic motors



ioptic
10-01-2009, 04:06
Hi,

am new to Thinbasic but an old hand at other flavours :)

I am a little confused about multitasking vrs line by line script interpreting.

I was using MSbasic and called stepper 3 motors with a turn command through the rs232 com port. In the order of 1turn, wait until stopped and then 2 turn wait until stopped and then three turn wait/suspend execution untill the motor has stopped.
But all three motors turned together is an uncontrollable, irratic robotic rage :) I am guessing that the loops just kept on executing all commands simultaniously- a sort of multithredding ).

So- here's me hoping that a scriting language like Thinbasic might be able to be stopped or suspended from exectution until a given task is completed.

Does anybody have a clue if thinbasic would wait politly for a task to stop before starting the next task ?

best regards
Rob
-o-o-

Petr Schreiber
10-01-2009, 04:28
Hi,

and welcome to the forums!

To make it easier to help you, could you show us code you use for turning motors?

Without seeing code, I would just suggest to use something like:


DIM finished AS LONG

' -- Function to turn motor #1
Turn_Motor(1)
finished = %FALSE

' -- Loop while we are not finished with turning
WHILE finished = %FALSE
' -- Did it finished or is it still turning? If finished, will return %TRUE
finished = Turn_Complete(1)

' -- Let CPU breath
DOEVENTS
WEND
' -- Continue here


or maybe more straightforward:


DIM finished AS LONG

' -- Function to turn motor #1
Turn_Motor(1)
finished = %FALSE

' -- Loop to wait UNTIL finished
DO
' -- Did it finished or is it still turning? If finished, will return %TRUE
finished = Turn_Complete(1)

' -- Let CPU breath
DOEVENTS
LOOP UNTIL finished = %TRUE


ThinBasic does not support multithreading yet, it just executes as fast as possible :).

If you know how long it can take to turn motors, you could also use SLEEP command to pause execution for few milliseconds. In such a case you would not need any WHILE/WEND or DO/LOOP cycles; Turn_Motor() could look like this then:


SUB Turn_Motor( steps AS LONG )
' -- Send data, do not know how, so enter your code here :)

SLEEP(steps * 100) ' -- If 100ms is time to make one step
END SUB

ioptic
10-01-2009, 05:28
Thanks for the welcome and the answer. Here is some code structure.

Not sure how you got yout code to look so good:)

It is basically right. But how do I stop the second motor from turning whike the first is still active ?
My MSBasic just starts all loops together, irrescpetive of the loops status. In robotics, we have many
motion rules and many need the wait before another task is started. Sometimes several motors need to start together
sometimes it is sequential and depending on another motors having stopped. etc...
What is important is to be able to stop the code from getting ahead of the motor action. Multithtredding is a feature of most compilers
but annoys me becuase my motors go beserk :)

Will ThinBasic actually wait in a loop before executing the command following the loop ?

best regards
Rob
-o-o-






'--------------------------------------------------
Open port 1

'--turn first motor---
send text command to motor 1 to turn 100 times

set motor status to turning

While motor status is turing (a simple accii text reply from port) stay in loop

check motor status

Do not execute next command untill motos has stopped.




'---turn second motor
send text command to motor 1 to turn 100 times

set motor status to turning


While motor status is turing (a simple accii text reply from port) stay in loop

check motor status

Do not execute next command untill motos has stopped.


'---turn third motor---
send text command to motor 1 to turn 100 times

set motor status to turning


While motor status is turing (a simple accii text reply from port) stay in loop

check motor status

Do not execute next command untill motos has stopped.

close port 1

eop.
'---------------------------------

Petr Schreiber
10-01-2009, 05:55
Hi,

* to make your code nice, use Syntax Highlight > thinBasic combobox when editing post, and place all code between inserted tags :)

* Adaptation of code ( In case it should move one motor after other ):


DIM i AS LONG

Motors_CommunicationOpen()

' -- Go through motor 1 to 3
FOR i = 1 TO 3

' -- Function to turn motor #i, 100 times
Motor_SetTurns(i, 100)
Motor_SetState(i, %TURNING)

' -- Loop to wait until state is not turning (=stopped)
WHILE Motor_GetState(i) = %TURNING

' -- Check status

WEND


NEXT

Motors_CommunicationClose()


For launching loops of all motors in "parallel":


Motors_CommunicationOpen()

' -- Function to turn motor #1-3, 100 times
Motor_SetTurns(1, 100)
Motor_SetTurns(2, 100)
Motor_SetTurns(3, 100)

Motor_SetState(1, %TURNING)
Motor_SetState(2, %TURNING)
Motor_SetState(3, %TURNING)

' -- Loop to wait until all motors stopped
DO

' -- Check status of all motors

LOOP UNTIL ( Motor_GetState(1) = %STOPPED AND Motor_GetState(2) = %STOPPED AND Motor_GetState(3) = %STOPPED )

Motors_CommunicationClose()


Hope it helps, must go now :)

Michael Hartlef
10-01-2009, 12:34
Hi Rob,

a big welcome here on the board. You have an interesting project going there. What do you control with these stepper motors?
One thing could help you automate something like this, could be the TBEM module. How long is a script running like this? Is the computer never turned off, or will it be shut down every day? Give me a little time to set up a script that can show you how you could do the logic for this with the TBEM module.

Anyway, feel free to ask any question and we will try to help you as best we can.

Michael

Michael Hartlef
10-01-2009, 12:36
Like Petr allready posted. Inside a loop that is runnign constantly, try to use allways the command DOEVENTS. It will give Windows time to react to other messages. If you don't do it, thinBasic will use 100% of CPU time.

ErosOlmi
10-01-2009, 13:16
Ciao Rob and welcome to thinBasic community forum.

Petr and Michael have already said all. I will contribute with a basic example using a Console Script showing how things can be implemented (hope to have understood in the right way).

Ciao
Eros



Uses "Console"

DIM lColor AS LONG VALUE 24
DIM SecsToWait AS LONG VALUE 30
DIM T1, T2 AS DOUBLE

type tMotors
IsWorking as long '---Only %TRUE if not inited and not stopped
CurrentActivity as long '---Indicates what the motor is doing
'---Add any additional info about a motor

'---Used to show specific motor data in the console
cX as long
cY as long
cW as long
cH as long

end type

'---Motors possible activities
%m_Inited = 10
%m_Starting = 20
%m_Started = 30
%m_Stopping = 40
%m_Stopped = 90

%MAX_Motors = 3


'-------------------------------------------------------------
function TBMAIN() as long
'-------------------------------------------------------------
local Motors(%MAX_Motors) as tMotors
local Counter as long

Console_SetTitle("Test Motors")
Console_Box(1,1,78,3,39,39,"Test Motors", 46, %Console_BOX_FLAG_3DOFF)

for Counter = 1 to %MAX_Motors
Motor_Init(Motors, Counter)
sleep 800 '---A little time just to show animation
next

Motor_Start (Motors, 1)
Motor_Stop (Motors, 1)

Motor_Start (Motors, 2)
Motor_Stop (Motors, 2)

Motor_Start (Motors, 3)
Motor_Stop (Motors, 3)

Printat "Press any key to finish.", 1, 25, 7
waitkey
cls

end function

'-------------------------------------------------------------
function Motor_Init(lMotors() as tMotors, MotorID as long) as long
'-------------------------------------------------------------
'---If a valid MotorID ... init it
if between(MotorID, 1, %MAX_Motors) then
Console_Box(1,1,78,3,39,39,"Test Motors", 46, %Console_BOX_FLAG_3DOFF)
lMotors(MotorID).IsWorking = %FALSE
lMotors(MotorID).CurrentActivity = %m_Inited

lMotors(MotorID).cX = 1 + (MotorID - 1) * 25
lMotors(MotorID).cY = 15
lMotors(MotorID).cW = 20
lMotors(MotorID).cH = 6

Console_Box( _
lMotors(MotorID).cX, _
lMotors(MotorID).cY, _
lMotors(MotorID).cW, _
lMotors(MotorID).cH, _
39, 39,"Motor " & MotorID & " Init", 46, %Console_BOX_FLAG_3DOFF)

function = %TRUE
end if


end function

'-------------------------------------------------------------
function Motor_Start(lMotors() as tMotors, MotorID as long) as long
'-------------------------------------------------------------
local Counter as long
local t as double

'---If a valid MotorID ... init it
if between(MotorID, 1, %MAX_Motors) then

Console_Box( _
lMotors(MotorID).cX, _
lMotors(MotorID).cY, _
lMotors(MotorID).cW, _
lMotors(MotorID).cH, _
62, 62,"Motor " & MotorID & " Starting", 62, %Console_BOX_FLAG_3DOFF)

lMotors(MotorID).IsWorking = %TRUE
lMotors(MotorID).CurrentActivity = %m_Starting

t = timer
'---Let say it takes 2 seconds to start ...
while (t + 2) > timer
printat mid$("/-\|", rnd(1,4),1), lMotors(MotorID).cX + 1, lMotors(MotorID).cY + 1, 62
doevents
wend

lMotors(MotorID).CurrentActivity = %m_Started
Console_Box( _
lMotors(MotorID).cX, _
lMotors(MotorID).cY, _
lMotors(MotorID).cW, _
lMotors(MotorID).cH, _
78, 78,"Motor " & MotorID & " STARTED", 78, %Console_BOX_FLAG_3DOFF)

function = %TRUE
end if


end function


'-------------------------------------------------------------
function Motor_Stop(lMotors() as tMotors, MotorID as long) as long
'-------------------------------------------------------------
local Counter as long
local t as double

'---If a valid MotorID ... init it
if between(MotorID, 1, %MAX_Motors) then

Console_Box( _
lMotors(MotorID).cX, _
lMotors(MotorID).cY, _
lMotors(MotorID).cW, _
lMotors(MotorID).cH, _
224, 224,"Motor " & MotorID & " Stopping", 224, %Console_BOX_FLAG_3DOFF)

lMotors(MotorID).IsWorking = %TRUE
lMotors(MotorID).CurrentActivity = %m_Starting

t = timer
'---Let say it takes 2 seconds to stop ...
while (t + 2) > timer
printat mid$("/-\|", rnd(1,4),1), lMotors(MotorID).cX + 1, lMotors(MotorID).cY + 1, 224
doevents
wend

lMotors(MotorID).CurrentActivity = %m_Started
Console_Box( _
lMotors(MotorID).cX, _
lMotors(MotorID).cY, _
lMotors(MotorID).cW, _
lMotors(MotorID).cH, _
110, 110,"Motor " & MotorID & " STOPPED", 110, %Console_BOX_FLAG_3DOFF)

function = %TRUE
end if


end function

Michael Hartlef
10-01-2009, 14:08
Hi Rob,

here is a little sample how you could use TBEM to repeatly and automatically call
procedures to control the flow of the script:




' Ron's Comm control sample via TBEM

'Load the modules
USES "console", "TBEM", "Comm"


'Declare some variables
dim hComm as dword
dim commPort as string value "COM1"
dim finish as long value %FALSE
dim retval as dword
dim event as long


'Declare some constants/equates
begin const
%evtStartMotor1 = 1
%evtStartMotor2
%evtCheckStatus1
%evtCheckStatus2
end const

'Now set the title of the console window
Console_SetTitle("Rob's stepper motor control sample")

'Sometimes it is still minimized, so send the command to show it
Console_ShowWindow(%Console_SW_SHOW)

'Let's open the comm port
console_writeline("Opening commPort ", commPort)
hComm = COMM_FreeFile
COMM_Open(commPort, hComm)


'Set up the events for the event manager module TBEM
'To start the motors, we add 2 events
event = TBEM_AddEvent("StartMotor1",%evtStartMotor1)
event = TBEM_AddEvent("StartMotor2",%evtStartMotor2)

'Next will be the events to check the status of motor1
event = TBEM_AddEvent("CheckStatus1",%evtCheckStatus1)

'As this event has to be called repeatly, set it's repeat value to 100 milliseconds
TBEM_SetRepeat(event, %TRUE, 100)


'Now add the events to check the status of motor2
event = TBEM_AddEvent("CheckStatus2",%evtCheckStatus2)

'As this event has to be called repeatly too, set it's repeat value to 100 milliseconds
TBEM_SetRepeat(event, %TRUE, 100)


'No event is running till now, so let's fire a trigger to get the ball rolling
TBEM_AddTrigger(%evtStartMotor1)

'In this loop, TBEM_RUN is called. It will check if a trigger for an event was fired, and activates/run this event
while finish = %FALSE
retval = TBEM_Run
doevents
wend

console_writeline("Closing commPort ", commPort)
comm_close(hComm)

console_writeline("Press any key...")
console_waitkey



'****************************************************************
' Declaration of event routines
'****************************************************************

'****************************************************************
sub StartMotor1()
' This event will run only once, as its repeat value is 0
'****************************************************************
COMM_Send(hComm, "Start motor 1")
console_writeline("Motor 1 start command send.")
'As the motor is running now, we have to check for it's state
TBEM_AddTrigger(%evtCheckStatus1)
end sub


'****************************************************************
sub StartMotor2()
' This event will run only once, as its repeat value is 0
'****************************************************************
COMM_Send(hComm, "Start motor 2")
console_writeline("Motor 2 start command send.")
'As the motor is running now, we have to check for it's state
TBEM_AddTrigger(%evtCheckStatus2)
end sub


'****************************************************************
sub CheckStatus1()
'This event will run every 100 milliseconds as it was defined above
'****************************************************************
local buffer as long value 0
local event as long

static running as long value %FALSE

COMM_Recv(hComm, 4, Buffer)
if buffer = 123 then
running = %TRUE
console_writeline("Motor 1 is running.")
end if
if running = %TRUE and buffer = 125 then
'We go the motor stopped command so let's kill this event
event = TBEM_GetCurrEventID
TBEM_DeleteEvent(event)
'And start the next motor
TBEM_AddTrigger(%evtStartMotor2)
end if
end sub


'****************************************************************
sub CheckStatus2()
'This event will run every 100 milliseconds as it was defined above
'****************************************************************
local buffer as long value 0
local event as long

static running as long value %FALSE

COMM_Recv(hComm, 4, Buffer)
if buffer = 123 then
running = %TRUE
console_writeline("Motor 2 is running.")
end if
if running = %TRUE and buffer = 125 then
'We go the motor stopped command so let's kill this event
event = TBEM_GetCurrEventID
TBEM_DeleteEvent(event)
'Set variable FINISH to TRUE so the whole script will be stopped
finish = %TRUE
end if
end sub




I could not test it fully as I have no experience will COMM port programming till now. Please replace the dummy commands with the stuff you need.

Michael

ioptic
11-01-2009, 08:40
Hi All!

I am truly impressed !
It's a bit like being in programmers heven :) and thanks to everyone !!!

I use robotics to measure stuff on an xy grid, the z being the surface rise/fall, a bit like mapping a lanscape in 3d or like using a laser line to measure stuff, only I needs it to be a mechanical probe, hence the motors.

I hope to then use some of the 3d and games code to bring this object/landscape to life, ie rotate it, zoom in and out etc..., change lighting angles etc... and I have a long way to go before I'll get there. But it looks like the TB community has seen these challenges before and I am glad I stumbles into it :)

TBEM -I looked it up in the internet help file, but the link was dead. But what I found sounded interesting. Where else can I find out what it is, what is does, how it works ?
---

Another challenge is to build an interactive Game. I am also looking at Blender, which I found as a recomendation on this site.
To be honest I am quite cluless about games. Ask me anything about databasing and Internet business tools and I am in more familiar teritory:)


There is quite a serious side to this game. It will be based on a social model/formula which prevents the rise of dictators, terrorism, hunger, wars etc... by showing the gamer alternatives to wars and violence (Ghandi's Satyagraha).
Only it's not just a game for entertainment (which would be tasteless). It's for real!
Imagine a game that could be configured to represent the Gaza conflict and you win when you put the fuse out and loose (get blown up) when you ingite it.
I am hopefully working on the social and economic formula's( Human formulas are like programming formulas. Just think of Tamagotchi babies/people? :) only infinatly more complex) / finetuning this year with a team of Rotary voluteers. We hope to develop and document the outcome as a methodology in peace building and hope to have it ultimatly accepted by the UN. (There is no point in living unless we can hit the occasional brick wall and as walls go this one is a beauty!)

But the ultimate would be a freely available interactive game... and being a natural pashionate programmer and systems alalyst- what better way for me then to try and begin to code/construct the logic and to get my all-to-a-big head around games logic, 3d. It should be a humbling experience :) etc...

How to start.. ahem... where is the Any key again? :)

Best regards
Rob
-o-o-

ErosOlmi
11-01-2009, 10:57
TBEM (thinBasic Event Manager) is a thinBasic module developed by Michael Hartlef.
You will not find info on it in Internet but only here in thinBasic community: http://community.thinbasic.com/index.php?board=154.0

TBEM implements a series of new thinBasic keywords allowing programmer to handle Events and Timing.
You can find a complete TBEM help file looking in \thinBasic\Help\ directory. File is thinbasic_TBEM.chm

Ciao
Eros

Michael Hartlef
11-01-2009, 12:48
Eros, I could produce HTML files to be put on a website. do you think it would be a good idea to create them and then link form the online manual to them?

Michael Hartlef
11-01-2009, 12:49
And Rob, I'm glad to see another one that wants to create a game with thinBasic. You will see that mostly everything is there for your idea. And if not, we will try to make it happen.

ErosOlmi
11-01-2009, 12:53
Eros, I could produce HTML files to be put on a website. do you think it would be a good idea to create them and then link form the online manual to them?


Well, all can be useful.
If you create them, I will be happy to reserve a space.

Ciao
Eros

ioptic
29-01-2009, 00:30
re motors.

here is a clue for anyone who is doing same motor driving.

IPM inches per minute are usully used to time motor functions, starting all motors from the same Zero second etc...
and suspending timeers for waiting tasks etc... Often you will also need a second or third timer etc... It's quite madening stuff :)


I am still working on Thinbasic and am not sure if loops work better in thinbasic, becuase they certainly don't work in
any other language- with any degree of reliabillity. Will post results when handy :)

best regards
Rob
-o-o-