' ************************************************************************** ' * * ' * PICAXE-18 MOTOR CONTROLLER FOR CYBOT AXE18BOT * ' * * ' ************************************************************************** ' * * ' * Program AXE18BOT.BAS * ' * * ' * Target PICAXE-18 * ' * Compiler Revolution Programming Editor 2.3.5 * ' * Memory Used 126 bytes of 128 ( 2 free ) * ' * * ' * Version 1.01 * ' * Created 2002-04-23 * ' * Last Modified 2002-07-22 * ' * * ' * Author The Happy Hippy * ' * Web Site http://www.psynet.net/hippy * ' * * ' * Copyright (C) 2002, The Happy Hippy * ' * * ' ************************************************************************** ' * * ' * DESCRIPTION * ' * * ' * This program monitors the serial line from the Brain, and turns * ' * motion requests into signals which are used to control the Cybot * ' * motor controller board. * ' * * ' * The LED flashes everytime a new request for motion is received. * ' * * ' * The interface should be connected to the Brain processor. TX from * ' * here goes to RX on the Brain. TX from the Brain comes to RX here, * ' * and to RX on the Motion Monitor processor. * ' * * ' * The interface connects to the Cybot motor controller board; check * ' * that the connections are correct, or you will damage the drive * ' * transistors on the motor controller board. * ' * * ' ************************************************************************** ' * * ' * CIRCUIT DIAGRAM * ' * * ' * .-. 22K * ' * PI |O|---.--===--. * ' * PO |O|<--|-------|--. * ' * PG |O|<--|-------|--|---. .------------. * ' * `-' `--===--|--|---{ | | * ' * .-. 10K | | | | 78L05 | * ' * 9V |O|-----------|--|---|----------------' .-----. | * ' * 5V |O|<----------|--|---|----------.--------|O I|<--' * ' * RX |O|-----------|--|---|----. | `--.--' * ' * TX |O|<-----. | | | | | | * ' * 0V |O|<-----|----|--|---^----|-----|-----------{ * ' * `-' | | | | | | * ' * .-------' | | | | | * ' * | .----------' | | | | * ' * | | .-----------' | | | * ' * | | | 4K7 | | | * ' * | | | .-------===-------|-----{ | * ' * | | | | | | | * ' * | | | | PICAXE-18 | | | .-------. * ' * | | | | .---------. | | | | \ * ' * | | | | | 1 18 | | | | .---. / * ' * | | `--|---| 2 17 | | | .--------|--->| 1 | \ * ' * | `----|-->| 3 16 | | | | .------|--->| 2 | / * ' * `---. `-->| 4 15 |<--' | | | .----|--->| 3 | \ * ' * .---|------| 5 14 |---------{ | | | .--|--->| 4 | / * ' * | `------| 6 13 |---------|--' | | | | | 5 | \ * ' * | | 7 12 |---------|----' | | | | 6 | / * ' * | .-----| 8 11 |---------|------' | }--->| 7 | \ * ' * | | .--| 9 10 |---------|--------' | `---' / * ' * | | | `---------' | | | \ * ' * | | `---===----. | | `--------' * ' * | | 2K2 _|_ | | Cybot Motor * ' * | +__|__ \ / LED __|__ | Drive Board * ' * | --.-- Piezo --.-- --.-- 100nF | * ' * | | | | | * ' * `----^-------------^-----------^-----------' * ' * * ' ************************************************************************** ' * * ' * HISTORY * ' * * ' * 1.00 2002-04-23 First public release * ' * * ' * 1.01 2002-07-22 Corrected "TX from here goes to RX on the * ' * Brain" line ( read "RX from .. to RX ..." * ' * * ' ************************************************************************** ' * * ' * KNOWN BUGS * ' * * ' * 1.00 2002-04-23 Typo in description. * ' * * ' * 1.01 2002-07-22 None. * ' * * ' ************************************************************************** ' ************************************************************************** ' * * ' * Define input pin usage * ' * * ' ************************************************************************** symbol RA0 = 0 ' RA0 / A2D0 symbol RA1 = 1 ' RA1 / A2D1 symbol RA2 = 2 ' RA2 / A2D2 symbol RX = 6 ' RA6 - Serial In symbol RA7 = 7 ' RA7 ' ************************************************************************** ' * * ' * Define output pin usage * ' * * ' ************************************************************************** symbol TX = 0 ' RB0 - Serial Out symbol TXNULL = 1 ' RB1 symbol PIEZO = 2 ' RB2 - Piezo Transducer symbol LED = 3 ' RB3 - LED symbol LHBOUT = 4 ' RB4 - Left Backwards symbol LHFOUT = 5 ' RB5 - Left Forward symbol RHBOUT = 6 ' RB6 - Right Backwards symbol RHFOUT = 7 ' RB7 - Right Forward symbol LEDMSK = %00001000 ' LED Bit Mask ' ************************************************************************** ' * * ' * Define constants * ' * * ' ************************************************************************** symbol BAUD = N2400 ' Maximum baud rate symbol FALSE = 0 symbol TRUE = 1 ' .------ Right Forward (RHFOUT) ' |.----- Right Backward (RHBOUT) ' ||.---- Left Forward (LHFOUT) ' |||.--- Left Backward (LHBOUT) ' |||| symbol STOP = %00000000 ' 0 Right Stop + Left Stop symbol TURNFORWARDLEFT = %10000000 ' 1 Right Fwd + Left Stop symbol TURNFORWARDRIGHT = %00100000 ' 2 Right Stop + Left Fwd symbol MOVEFORWARD = %10100000 ' 3 Right Fwd + Left Fwd symbol MOVEBACKWARDS = %01010000 ' 4 Right Back + Left Back symbol TURNBACKWARDSLEFT = %01000000 ' 5 Right Back + Left Stop symbol TURNBACKWARDSRIGHT = %00010000 ' 6 Right Stop + Left Back symbol SPINLEFT = %10010000 ' 7 Right Fwd + Left Back symbol SPINRIGHT = %01100000 ' 8 Right Back + Left Fwd ' %11xxxxxx Burns out left motor drive ' %xx11xxxx Burns out right motor drive ' %1111xxxx Burns out both motor drives ' ************************************************************************** ' * * ' * Define variables * ' * * ' ************************************************************************** symbol dataReceived = b0 ' Data received from Brain symbol dataType = b1 ' Type of data received symbol speedRequired = b2 ' Speed requested by Brain symbol motionRequired = b3 ' Motion requested by Brain symbol motorBits = b4 ' Motor drive bits symbol otherBits = b5 ' Other output bits symbol lastDataReceived = b6 ' Previous data received from Brain symbol pwmCycle = b7 ' PWM cycle counter symbol hadAlarm = b8 ' Sounded alarm flag ' ************************************************************************** ' * * ' * Program Initialisation * ' * * ' ************************************************************************** ' The program starts execution here when the processor is powered up, is ' reset, and after the program has been downloaded. ' ' The output pins are immediately cleared to prevent any damage to the motor ' control board, and then the program issues two low frequency beeps on the ' piezo transducer to indicate it has initialised, and then waits just under ' 4S to allow the other processors to be initialised ( and power to be ' applied to the motors if switched off ). ' ' The Motor Controller will send its first serial synchronisation byte 5S ' after it is reset, the Brain will respond shortly after that. Start: pins = 0 ' Turn all outputs off pause 850 sound PIEZO,(80,25) ' Issue two low frequency beeps pause 60 sound PIEZO,(80,20) pins = 0 ' Turn all outputs off pause 4150 ' Wait until 5S from reset ' ************************************************************************** ' * * ' * Main Program Loop * ' * * ' ************************************************************************** ' Every loop is started by the program sending out a synchronisation byte. ' The content of the byte could be anything, but we send a copy of the input ' pins so the Brain processor can, if it wants to, see what is happening to ' the four otherwise unused inputs on this chip. This extends the input ' capability of the Brain quite considerably. SendSynchronisationByte: serout TX,BAUD,(pins) ' ************************************************************************** ' * * ' * Handle Received Data * ' * * ' ************************************************************************** ' Immediately after sending the synchronisation byte, we wait to receive a ' serial byte back from the Brain. The format of the byte is - ' ' .-----------.-----------.-----------------------. ' | t | t | s | s | m | m | m | m | ' `-----------^-----------^-----------------------' ' ' where t is type, if not 00 we ignore the data received ' s is Speed, 0 = slowest .. 3 = fastest ' m is Motion required, 0 .. 15 ' ' 0 = Stop 7 = Turn Left ' 1 = Forward Left 8 = Turn Right ' 2 = Forward Right ' 3 = Move Forward 9 ..11 = Rotate Left ' 4 = Move Backward 12..14 = Rotate Right ' 5 = Backwards left ' 6 = Backwards Right 15 = Stop for 10S ' ' If the requested motion is exacttly the same as the last request, we do ' not process it, but continue to use the perevious data. This allows the ' loop time to be minimised and keep the PWM cycles consistent. ' ' If the type is not 00, we ignore the data received. ' ' If we have a new motion request, we toggle the LED on/off. ' ' The speed is extracted, and will later be used to determine in which ' phases of the PWM cycle the motors should be turned on. ' ' The motion is extracted from the received byte, and is used as an index ' into a table which determines which motor drive bits should be set to ' achieve the motion requested. ' ' Note that we do not handle fixed angular rotations yet ( motions 9..15 ). ' If we receive a rotation motion request, we simply stop the motors, until ' we receive a motion we can provide. ' ' We are using the 'read' and 'eeprom' commands because these use less code ' space than the equivalent 'lookup', and it also makes the program more ' readable. WaitForDataToBeReceived: serin RX,BAUD,dataReceived CheckIfDataReceivedIsSameAsLast: if dataReceived = lastDataReceived then NoNewMotionRequest lastDataReceived = dataReceived CheckDataTypeIs00: dataType = dataReceived & %11000000 if dataType <> %0000000 then NoNewMotionRequest ToggleLed: otherBits = otherBits ^ LEDMSK DetermineSpeedRequired: speedRequired = dataReceived & %00110000 / 16 DetermineMotionRequired: motionRequired = dataReceived & %00001111 GetMotorBitsToUse: if motionRequired > 8 then HandleRotations read motionRequired,motorBits eeprom (STOP) ' 0 eeprom (TURNFORWARDLEFT) ' 1 eeprom (TURNFORWARDRIGHT) ' 2 eeprom (MOVEFORWARD) ' 3 eeprom (MOVEBACKWARDS) ' 4 eeprom (TURNBACKWARDSLEFT) ' 5 eeprom (TURNBACKWARDSRIGHT) ' 6 eeprom (SPINLEFT) ' 7 eeprom (SPINRIGHT) ' 8 goto MotorBitsHaveBeenDetermined HandleRotations: motorBits = STOP MotorBitsHaveBeenDetermined: NoNewMotionRequest: ' ************************************************************************** ' * * ' * Update Motor Drive Bits * ' * * ' ************************************************************************** ' The PWM cycle time depends upon how frequently we arrive at this point in ' program. The more accurate the time taken between arrival determines the ' stability of the PWM. The SEROUT and SERIN take around 4mS each at 2400 ' baud, so we should arrive here every 8mS or so. ' ' The PWM runs with a four phase cycle, 0..3, so the entire cycle time is ' 32mS approximately. ' ' The PWM cycle is compared with the speed required to determine if the ' motors should be turned on or off. Slower speeds will have the motors ' turned off most of the time, while higher speeds will have motors turned ' on most of the time. ' ' ' |0|1|2|3|0| |0|1|2|3|0| |0|1|2|3|0| |0|1|2|3|0| |0|1|2|3|0| ' _ _ ___ ___ _____ ___ ___________ ' ___________ _| |_____| |_ _| |___| _| |_| ' ' 0% 25% 50% 75% 100% ' Stop Slowest Full On ' ' Ideally, the 50% duty cucle should present the following sequence, but ' this has not been implemented. ' ' |0|1|2|3|0| ' _ _ _ ' _| |_| |_| |_ ' ' 50% ' ' When the PWM cycle indicates the motors should be on, the outputs are set ' with the motor bits and the LED bits. Ehen the motors should be off, the ' outputs are set by just the LED bits. The other bits will always remain ' zero, which has the effect of turning the motors off. ' ' When the motor drive and LED bits are set, and the program issues another ' synchronisation byte, then waits to receive the next motion request byte ' from the Brain. The entire process is then repeated. ' ' The program continues until powered off, reset, or reprogrammed. UpdatePwmCycle: pwmCycle = pwmCycle + 1 & 3 DeterminePwmState: if speedRequired >= pwmCycle then PwmOn PwmOff: pins = otherBits goto CheckIfStopFor10S PwmOn: pins = motorBits | otherBits CheckIfStopFor10S: if motionRequired <> 15 then CancelAlarm if hadAlarm = TRUE then HaveHadAlarm SoundAlarm: sound PIEZO,(120,25,80,25) hadAlarm = TRUE ReallyStopFor10S: pause 10000 HaveHadAlarm: goto SendSynchronisationByte CancelAlarm: hadAlarm = FALSE goto SendSynchronisationByte ' ************************************************************************** ' * * ' * End of source code * ' * * ' **************************************************************************