How to use Bot Board II and Bais atom/pro to cantrol relay w

Hi, Kurt
I wish to program my Bot Board II and Basic atom/pro to cantrol a servo and relay as a switch for higher voltage, like:
1 second after the relay gets “on”, the servo starts travel from position 1 to position 2 (180 degrees), 1 second after the servo reaches position 1, the relay gets “off”, and “pause” 4 seconds, the relay gets “on”, and 1 second later, the servo starts travel from position 2 to position 1 (180 degrees), and 1 second after the servo reaches position 2, the relay gets “off”, and after repeat 6 times then get a longer “pause” (one hour)…
I tried many times to modify the program, which you made for me last time, to meet this need by replacing a servo with a relay and changing some codes, but I could not get it work. I believe I have to bother you again.
Could you do me one more favor for this? I’ll appreciate it very much.
Thank you.
Yongxin

What sort of relay are you using? How is it connected?

Hi, Jim,
I am glad hearing from you.

The relay I am using is Zettler AZ831-2C-5DSE, 5 volts, I coneect it like: black wire----relay-----yellow wire, I think it is negative–relay—signal. I left the middle wire (positive) out. I tried a some codes like:

counter var word ;must define variables
EMS con P5 ;EMS on P5

loop ;main program loop
high EMS ;turn on EMS
pause 6000 ;wait 6 seconds
low EMS ;turn off EMS
pause 4000 ;wait 4 seconds
high EMS ;turn on EMS
pause 6000 ;wait 6 seconds
low EMS ;turn off EMS
pause 4000 ;wait 4 seconds

It seams work except that it did not really make “loop” like when I ran other programs you made for me. And I do not know how to get the relay and the servo work together.
(EMS is my relay)
Yongxin

The coil is between pins 1 and 16. The coil sensitivity is 100mW, so at 3.75vdc (pickup) the current is 27mA, however if you use the coil resistance of 125 ohms, the current is 30mA. For discrete outputs (Hi / Low), each output can sync or source up to 35mA. However there is a maximum limit of 70mA per 8 I/O pin group. I.e. 0-7, 8-15, 16-23, 24-31.

What this means is the SSC-32 should be able to energize the relay by directly connecting it to the ground and signal. But you must not have more than two relays on a bank of eight outputs.

So attach the ground to pin 16 and the signal to pin 1. When energized, do you here any clicking sound from the relay?

To send a high or low to a servo channel you would send it:
#0 H CR, or #0 L CR

I would try to help you put this into your program, can you post it here?

Thank you, Jim,
I do not have SSC-32 in hands, so I am going to place a order for it, but it will take several days to get it here.
The pin 16 and pin 1 you mentioned are on SSC-32?
What I should do is to program the servo and the relay separately with Bot Board II and SSC-32 and link these two boards together, right?
Do I have any chance to use one board to control both? For example, do you have such a relay which could be used with Bot Board II and I can order from Lynxmotion?
Yongxin

I’m sorry, I forgot that you are using BotBoard II not SSC-32. You do not need to buy the SSC-32. I’m not sure what the current rating is on the Atom Pro module. I will have to do some research.

In your testing has the relay made any clicking sounds? Do you think it is energizing? Do you need to know how to make the program loop? Just add goto loop at the end.

In my testing the relay made some clicking sounds, but not last long enough. I just tested it again and I do not think it was energizing, because I could not detect any changes of resistence, current and voltage at the output ends of relay, but I did detect the voltage changes from 0 to 5 and from 5 to 0 on I/O pins when I ran the program. It may not get enought current as you said. What should I do with it?
Now I know how to make the program loop :slight_smile:. Thank you so much.
Yongxin

Hi, Jim,
I tried another relay with the new “loop” program, it worked very well :smiley: . It means something was wrong with my first relay.
Now the last question remains how to program the servo and relay together. Could you help me to write some codes for this? Following are the codes for running 2 servos, which was writthen by Kurt. I tried to modify them to fit one servo and one relay, but I failed many times.
Thank you very much.
Yongxin

[code]
; Program to sweep different servos back and forth over a given time…
NUMSERVOS con 2
; variables and constants associated with system timer
lTimerCnt var long
lCurrentTime var long

; Warning on the timings I am going to further divide the clock value by 4, which will give us a precision of about 2ms,
;but will keep our clock from overflowing for over 100 days…
;This requires changes in, our multiplier below, plus in the timer interrupt and in our GetCurrentTime function.
WTIMERTICSPERMSMUL con 64*4 ; BAP28 is 16mhz need a multiplyer and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 125 ;

STATE_START_CYCLE con 0
STATE_SWEEP_1 con 1
STATE_SWEEP_2 con 2
STATE_LONG_WAIT con 3

ServoState var byte(NUMSERVOS)
ServoTimeNext var long(NUMSERVOS)
ServoLoopCnt var byte(NUMSERVOS)

iServo var byte

SERVO_TABLE bytetable P4, P5
POSITION1_TABLE swordtable -9000, -9000 ; What position to use for each servo for position 1
POSITION2_TABLE swordtable 9000, 9000 ; … Position 2
MOVETIME1_TABLE wordtable 500, 500 ; how much time to go to position 1 in ms
MOVETIME2_TABLE wordtable 500, 500 ; how much time to go to position 2 in ms

; Note the following tables are stored in Timer units. The timer is init to increment every 8192 clock cycles
; so to convert from Clock Cycles(CS) to Milliseconds(ms) we have ms = (cs * 8192)1000/16000000 reduced to cs64/125
; but table is in cs to convert ms to cs we have cs=ms125/64
; note below using defines from other programs as if you run on Arc32 it runs at 20mhz so constants change
INIT_WAIT_TABLE longtable 0, (5000
WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL ; how many ms to delay each servo from starting
TIME1_TABLE longtable (2000WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL, (2000WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL ; how long the time 1 should be
TIME2_TABLE longtable (2000WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL, (2000WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL ; likewise for time 2…
LONGWAIT_TABLE longtable (601000WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL, (601000WTIMERTICSPERMSDIV)/WTIMERTICSPERMSMUL ; setup long wait time… for me minute…

NUMCYCLES_TABLE bytetable 5, 5

for iServo = 0 to NumServos-1
ServoState(iServo) = STATE_START_CYCLE
ServoTimeNext(iServo) = INIT_WAIT_TABLE(iServo)
ServoLoopCnt(iServo) = 0;
next

; Init our system timer
gosub InitTimer

Loop:
; check to see if any of our servos need handling
gosub GetCurrentTime ; this sets lCurrentTime
for iServo = 0 to NUMSERVOS-1
if lCurrentTime > ServoTimeNext(iServo) then
if ServoState(iServo) = STATE_START_CYCLE then
ServoState(iServo) = STATE_SWEEP_1 ; set up new state
gosub MoveServo[Servo_Table(iServo), POSITION1_TABLE(iServo), MOVETIME1_TABLE(iServo)]
ServoTimeNext(iServo) = ServoTimeNext(iServo) + TIME1_TABLE(iServo) ; set up for when the next time for something to happen

     elseif ServoState(iServo) = STATE_SWEEP_1
        ServoState(iServo) = STATE_SWEEP_2      ; set up new state
        gosub MoveServo[Servo_Table(iServo), POSITION2_TABLE(iServo), MOVETIME2_TABLE(iServo)]
        ServoTimeNext(iServo) = ServoTimeNext(iServo) + TIME2_TABLE(iServo)   ; set up for when the next time for something to happen

     elseif ServoState(iServo) = STATE_SWEEP_2
        ; We completed a complete cycle, lets increment our count of iterations.  If we reach max count we will go into long
        ; wait else we will start the next cycle...
        ServoLoopCnt(iServo) = ServoLoopCnt(iServo) + 1
        if ServoLoopCnt(iServo) >= NUMCYCLES_TABLE(iServo) then 
           ; set up for the long wait
           ServoTimeNext(iServo) = ServoTimeNext(iServo) + LONGWAIT_TABLE(iServo)   ; set up for when the next time for something to happen
           ServoLoopCnt(iServo) = 0 ; reset counter
           HSERVO[Servo_Table(iServo)\-24000\0]   ; special number to tell analog servos to power down (send no more signals). 
        endif
        ServoState(iServo) = STATE_START_CYCLE
     endif
  
  endif   

next

goto loop

_MS_Servo var byte
_MS_Pos var sword
_MS_Time var long
MoveServo[_MS_Servo, _MS_Pos, _MS_Time]:
HServo [_MS_Servo_MS_Pos(ABS(_MS_Pos - (HServoPos _MS_Servo))*20)/_MS_Time]
; HServoWait[_MS_Servo]
return

;========================================================================================================
; Note the code below is used to setup a system timer that we use to time maintain the timings in the program
;====================================================================
;--------------------------------------------------------------------
;[TIMER INTERRUPT INIT]
TIMERINT con TIMERAINT
ONASMINTERRUPT TIMERAINT, HANDLE_TIMERA_ASM
InitTimer:
;Timer
; Timer A init, used for timing of messages and some times for timing code…
TIMERINT con TIMERAINT

WTIMERTICSPERMSMUL con 64 ; BAP28 is 16mhz need a multiplyer and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 125 ;
TMA = 0 ; clock / 8192 ; Low resolution clock - used for timeouts…
lTimerCnt = 0 ; initialize our timer to 0
ENABLE TIMERINT

return

;==============================================================================
;[Handle_Timer_asm] - Handle timer A overflow in assembly language. Currently only
;used for timings for debuging the speed of the code
;Now used to time how long since we received a message from the remote.
;this is important when we are in the NEW message mode, as we could be hung
;out with the robot walking and no new commands coming in.
;==============================================================================
BEGINASMSUB
HANDLE_TIMERA_ASM
push.l er1 ; first save away ER1 as we will mess with it.
bclr #6,@IRR1:8 ; clear the cooresponding bit in the interrupt pending mask
mov.l @LTIMERCNT:16,er1 ; Add 256 to our counter - Note changed to 64 as we are changing the clock to overflow
add.l #64,er1 ; only after about 100 days instead of 25
mov.l er1, @LTIMERCNT:16
pop.l er1
rte
ENDASMSUB

;-------------------------------------------------------------------------------------
;==============================================================================
;[GetCurrentTime] - Gets the Timer value from our overflow counter as well as the TCA counter. It
; makes sure of consistancy. That is it is very posible that
; after we grabed the timers value it overflows, before we grab the other part
; so we check to make sure it is correct and if necesary regrab things.
; Warning: Changed function to divide clock by 4 to allow a slower overflow…
;==============================================================================
GetCurrentTime:
lCurrentTime = lTimerCnt + TCA/4

; handle wrap
if lTimerCnt <> (lCurrentTime & 0xffffffC0) then ’ Had to modify mask as well as only updating lower 6 bits…
lCurrentTime = lTimerCnt + TCA/4
endif

return lCurrentTime[/code]

Glad you got the relay to work. Unfortunately I’m not able to help with the code… Sorry

Anyway, thanks.
Then, could you tell me where I can find the detail information about how to make the codes for Bot Board II and Bais atom/pro? I could not find it in your website and your codes are different from others as you said somewhere in this forum. I do wish to learn the meanings of these codes and how to use them…
Thank you again.
Yongxin

I would like to help you, but I don’t understand the code. Kurt is much more advanced than I am with coding. There is a syntax manual built into the BM Studio program you are using. There is also context sensitive help built in as well. Your commands to make the I/O pin go high and low are correct. You just need to put them into the program in the right place.

So far I don’t see anything different in the code that I posted and what you posted. Did you make changes?

If it were me, I would try a couple of different approaches…

  1. Use one of the relays that is setup to take servo pulses: Such as basicmicro.com/Power-Switch- … _p_44.html Also DimensionEngineering also makes some…

  2. Could try to hack the tables to simply turn the servo on and off. I know that if you use the value:
    -24000 it will turn the servo off, as the code converts this to a pulse width of 0… There are thread on this. What I have never tried is a value of +24000, this should say to HSERVO that the pulse width is 3000us, which may work just fine (or not)

  3. Put special values in the tables that says turn on or off. Since your values never use values 0 or 1 in the tables, you could use them. If it were me and I wanted it to keep the code general purpose, I would choose two values that are not in the valid ranges. Like maybe:
    32000 is Off value and 32001 is On. Then you could change the function MoveServo, to add code that says something like:

; up top somewhere... POSITION_ON con 32000 POSITION_OFF con 32001 ;... _MS_Servo var byte _MS_Pos var sword _MS_Time var long MoveServo[_MS_Servo, _MS_Pos, _MS_Time]: if _MS_Pos = POSITION_ON then high _MS_Servo elseif _MS_Pos = POSITION_OFF low _MS_Servo else HServo [_MS_Servo\_MS_Pos\(ABS(_MS_Pos - (HServoPos _MS_Servo))*20)/_MS_Time] return

  1. Could duplicate the servo loop code to create a table of Relay on/off times and simply loop through that. Again you need states as you can not pause or the rest of the code will not work.

Good Luck
Kurt

Hi, kurt,
I am so glad you are here today :smiley:.
These are still yours and worked great as I told you. The changes I made for relay never worked and got many errors. Probably I messed them up. I am going to do following you instruction.
Thank you so much.
Yongxin