Skip to main content

FLL EV3 Robot

This blog post is about our current EV3 robot we're planning to use in the 2023/2024 FLL competition. Some features: 2 large motors for steering. 2 medium motors for attachments.  2 colour sensors for picking up the white and black lines, also used for line squaring. 1 gyro sensor. To enable attachments to be changed as quickly as possible we're using gravity to keep the gears connected, i.e. you don't need to fasten anything to the robot. Every attachment has 2x 12 tooth double bevel gear (part 32270) which comes in contact with the 2x 20 tooth double bevel gears (part 32269) on the robot. The medium motors are horizontally aligned on the robots, but we use 12 tooth double bevel gears to convert that to vertical alignments. These in turn are connected to 20 tooth double bevel gears, and the attachments in turn connect to these 20 tooth double bevel gears with their 12 tooth double bevel gears.  The complete robot is modelled in Bricklink Studio 2 . You can download the rob

8051 HEX file upload code

NumBytes equ 040h
Choice equ 041h
CRC equ 042h
LineCount equ 043h
Counter equ 044h
Counter2 equ 045h
BaseH equ 046h ; Base address of SRAM
BaseL equ 047h
HexCount equ 048h ; 16 hex chars/line counter

Endflag equ 20h
Hexflag equ 21h

org 0000h
ljmp Main

org 0020h

Main:
lcall Init ; Initialise hardware
mov BaseH, #0E0h ; Set default base E000h
mov BaseL, #000h
mov dptr, #WelcomeMessage
lcall SendString ; Print welcome message
lcall SendCRLF
MenuLoop:
mov dptr, #MenuMessage
lcall SendString ; Show options
Wait:
jnb RI, Wait ; Wait until a char is received from serial port
lcall Receive ; Get char in accumulator
mov choice, a ; save choice
mov dptr, #OptionList ; Points to valid options string
lcall Position ; determine if char is a valid choice
jz Invalid
dec a ; 0 is first option
push acc
lcall SendCRLF
pop acc
lcall Branch ; Execute option
lcall SendCRLF
sjmp MenuLoop ; Start menu again
Invalid:
mov a, choice ; retreive choice
lcall Send ; send char back
mov dptr, #InvalidMessage
lcall SendString ; Show that choice is invalid
sjmp Wait ; Wait for a valid char

SetBase:
mov dptr, #BaseAskMessage
lcall SendString
lcall ReceiveHex
mov BaseH, a
lcall SendHex
lcall ReceiveHex
mov BaseL, a
lcall SendHex
lcall SendCRLF
ret

Download:
mov dptr, #DownloadMessage
lcall SendString ; Show message
mov LineCount, #0
clr EndFlag

StartLine:
inc LineCount
WaitColon:
lcall Receive
cjne A, #':', WaitColon

ProcessLine:
mov CRC, #0
lcall ReceiveHex
mov NumBytes, a
lcall ReceiveHex
add a, BaseH ; adjust for RAM mapping
mov dph, a
lcall ReceiveHex
add a, BaseL ; adjust for RAM mapping
mov dpl, a
jnc ContinueProcess
inc dph ; correct pointer
ContinueProcess:
lcall ReceiveHex
jz ReceiveData
setb EndFlag
mov NumBytes, #0
ReceiveData:
mov a, NumBytes
jz CheckSum
lcall ReceiveHex
movx @dptr, a
inc dptr
dec NumBytes
sjmp ReceiveData

CheckSum:
lcall ReceiveHex
mov a, CRC
jnz ChecksumError
jnb EndFlag, StartLine

ReceivedOK:
mov dptr, #DownloadOK
lcall SendString
lcall SendCRLF
lcall Receive ; Eat last byte
ret

CheckSumError:
mov dptr, #DownloadErr
lcall SendString
mov a, LineCount
lcall SendASCII
lcall SendCRLF
ret

ReceiveHex:
lcall Receive
lcall Hex2Num
mov B, #010h
mul AB
mov r7, a
lcall Receive
lcall Hex2Num
add a, r7
push acc
add a, CRC
mov CRC, a
pop acc
ret

Hex2Num:
clr c
subb A, #030h ; Convert 0-9
cjne A, #009h, AdjustNumber
ret
AdjustNumber:
jc EndConvert
subb A, #007h ; convert A-F

EndConvert:
ret

Verify:
mov hexcount, #10h
mov dptr, #VerifyMessage
lcall SendString ; Show message
lcall ReceiveHex ; Get size
mov Counter, a
lcall SendHex
lcall ReceiveHex
mov Counter2, a
lcall SendHex
lcall SendCRLF
mov dptr, #DumpMessage
lcall SendString
lcall Receive ; Hex or ASCII mode
clr HexFlag
cjne a, #'H', ASCIIDump
setb HexFlag ; Hex mode
ASCIIDump:
lcall SendCRLF
mov dph, BaseH
mov dpl, BaseL

VerifyByteLoop:
mov a, Counter2
jz Counter1Loop
dec Counter2
ajmp VerifyOutput

Counter1Loop:
mov a, Counter
jz VerifyEnd
dec Counter
mov Counter2, #0FFh
ajmp VerifyOutput
VerifyEnd:
ret

VerifyOutput:
movx a, @dptr ; read ram
jb HexFlag, VerifyHex
lcall Send ; send char
ajmp OutputEnd
VerifyHex:
lcall SendHex ; send char in HEX format
djnz HexCount, HexSpace
mov HexCount, #10h ; 16 chars / line
lcall SendCRLF
ajmp OutputEnd
HexSpace:
mov a, #' '
lcall Send
OutputEnd:
inc dptr
ajmp VerifyByteLoop

;============================================================================
;Hardware initialisation
;============================================================================

Init: ; Setup all hardware
mov ip, #00000010b ; Interrupt priority: T0,SER,T1,INT1,INT0
; effectivly T0,INT1 - others not used
mov tmod, #00100010b ; set timer 0 & 1 to 8-bit auto-reload mode
mov th1, #0fdh ; timer 1 reload value: 256-253=3
; 11.0592Mhz / 12 / 32 / 3 = 9600 baud
mov pcon, #10000000b ; double baudrate : 19.2k
mov scon, #01010000b ; 8-bit UART & enable reception
mov tcon, #01000000b ; run timer 1
mov ie, #00000000b ; Disable all interrupts
ret

;============================================================================
;3-way branching routine
; use r7
;============================================================================

Branch:
clr c
rlc a ; Multiply by 2 (2 bytes)
mov r7, a ; Save choice in r7
mov dptr, #OptionTable ; Point to base of table
inc a
movc a, @a+dptr ; Read MSB in acc
push acc
mov a, r7 ; Reload choice
movc a, @a+dptr ; Read LSB in acc
push acc
ret ; branch to address

;========================================================================
; Determine position of char (in acc) in a string pointed by DPTR.
; Position returned in accumulator, 1=first char, 0 = not found
; Use r6 & r7
;========================================================================

Position:
mov r7, a ; Store char in R7
mov r6, #0 ; set index to 0
Compare:
mov a, r6 ; load index
inc r6 ; increase index to next char
movc a, @a+dptr ; read in char
jz ExitPosition ; exit if at end of string
clr c ; clear carry for subtraction
subb a, r7 ; subtract char from acc
jnz Compare ; no match
mov a, r6 ; return with index in acc
ret
ExitPosition:
ret

;========================================
;Convert char in acc to uppercase
;========================================

UpperCase:
cjne a, #60h, Greatera ; Test if char >= 'a'
sjmp OtherChar ; char equal to 60h
Greatera:
jc OtherChar ; not >= 'a'
cjne a, #7Bh, Lessz ; test if char <= 'z'
sjmp OtherChar
Lessz:
jnc OtherChar ; not <= 'z'
clr c ; clear carry for subtraction
subb a, #20h ; convert to uppercase
OtherChar:
ret

;============================================================================
;Sends char in accumulator out the serial port
;============================================================================

Send:
clr TI ; Clear transmit interrupt flag
mov sbuf, a ; Put char in transmit buffer
SendSerialLoop:
jnb TI, SendSerialLoop ; Wait until char is transmitted
ret

;============================================================================
;Receives a char from the serial port and stores it in the accumulator
;============================================================================

Receive:
jnb RI, Receive ; Wait until char is received
mov a, sbuf ; Read char into accumulator
clr RI ; Clear receive interrupt flag
lcall Uppercase ; Convert char to uppercase
ret

;============================================================================
;Sends number in accumulator out the serial port in HEX format
; Use r7
;============================================================================

SendHex:
mov r7, a ; Save accumulator in R7
swap a ; Most significant 4 bits first
lcall Lookup_Send ; Send first hex digit
mov a, r7 ; Reload original value
lcall Lookup_Send ; Send second hex digit
ret

;============================================================================
;Sends number in accumulator out the serial port in ASCII format
; Use r6 & r7
;============================================================================

SendASCII:
mov r7, a ; Save accumulator in R7
mov b, #100d
div ab ; divide acc by 100
lcall Lookup_Send ; send first digit
mov b, #100d
mul ab ; value of byte send
mov r6, a ; store value in r6
mov a, r7 ; restore original value
clr c ; clear carry bit
subb a, r6 ; remaining value to send
mov r7, a ; save remaining value in r7
mov b, #10d
div ab ; divide acc by 10
lcall Lookup_Send ; send second digit
mov b, #10d
mul ab ; value of byte send
mov r6, a ; store value in r6
mov a, r7 ; restore original value
clr c ; clear carry bit
subb a, r6 ; remaining value to send
lcall Lookup_Send ; send last digit
ret

Lookup_Send: ; Convert a decimal/hex digit to ASCII
push acc ; save acc on stack
anl a, #00001111b ; Mask off 4 bits
add a, #0f6h ; overflow if digit > 9
jnc NoAdjust ; no overflow digit <= 9
add a, #07h ; Adjust for hex digits (A-F)
NoAdjust:
add a, #3ah ; Adjust for ASCII
lcall send ; Send char to serial port
pop acc ; reload acc from stack
ret

;============================================================================
;Sends a null-terminated string to the serial port. DPTR=Begin address
; - modifies a & dptr
;============================================================================

SendString:
clr a ; no offset from DPTR
movc a, @a+dptr ; input first char in acc
jz SendString_End ; null-termination
inc dptr ; point to next char
lcall Send ; send current char
sjmp SendString
SendString_End:
ret

;============================================================================
;Send Carriage Return and Line Feed to the serial port
;============================================================================

SendCRLF:
mov a, #0dh ; send CR
lcall Send
mov a, #0ah ; send LF
lcall Send
ret

;============================================================================
;Menu choices & addresses
;============================================================================

OptionList:
db "BDV", 0h

OptionTable:
dw SetBase
dw Download
dw Verify

;============================================================================
;Message strings
;============================================================================

WelcomeMessage:
db "MCS51 Hex File Download program", 0dh, 0ah, "Johan Bijker - Jun 2000", 0h
MenuMessage:
db "(B)ase, (D)ownload, (V)erify: ", 0h
InvalidMessage:
db " is invalid! ", 0h
BaseAskMessage:
db "Enter base address (4 hex bytes): ", 0h
DownloadMessage:
db "Downloading... ", 0h
DownloadOK:
db "Download completed!", 0h
DownloadErr:
db "Error in line ", 0h
VerifyMessage:
db "Enter size (4 hex bytes): ", 0h
DumpMessage:
db "(H)ex or (A)SCII? ", 0h

end ; End of HEX downloader

Comments

Popular posts from this blog

Installing Lego Digital Designer (LDD) on Windows 10

If you're using Windows 10 18.09 or later and try to install Lego Digital Designer (LDD) 4.3.11 you'll probably get an installation error for Adobe Flash Player. However, there is an easy way around it: Download the installation file for LDD 4.3.11. Rename the .exe file to .zip. If you don't see the .exe extension in Explorer, go to "View - Options" on the Explorer menu, then under the "View" tab deselect the "Hide extensions for known file types". Open the zip file with Windows Explorer. Copy all files in the zip to another directory on your computer. In the new folder: Delete install_flash_player_active_x.exe. Copy OpenGLChecker.exe and rename it to install_flash_player_active_x.exe. Run LDDSetup.exe. In short the installer will execute install_flash_player_active_x.exe during the installation process, but all it does now is to execute the same logic as what OpenGLChecker does. In theory you can run any .exe that will not retu

OpenWRT 3G connection checker & logger

A 3G connection is normally not very stable - so we need something to periodically check it & reconnect when needed. I also wanted a summary email at the end of each day with the total traffic per client. I'm using the following settings/scripts: Edit /etc/crontabs/root (create if not existing): # send stats & disconnect 3G at 23:00 everyday. # check the connection every 5 minutes between 5:00 and 23:00 and reconnect if needed # reboot at 5:00 if /tmp/stats.msg doesn't exist - will be sent in checkconnect */5 5-22 * * * /usr/bin/checkconnection 0 5 * * * if [ ! -s /tmp/stats.msg ]; then reboot ; fi 0 23 * * * /usr/bin/sendstats && ifdown wan The first line will run /usr/bin/checkconnection every 5 minutes between 5:00 and 22:59. Then at 23:00 the  day's statistics will be emailed and the 3G connection disconnected. The next morning at 5:00 it first checks if the email was sucessfully sent at 23:00, if so it will reboot the router (seems to be m

Windows Hyper-V Server 2019

This post will explain how to use the free Hyper-V Windows 2019 Server version. This version doesn't come with any GUI interface as provided in the full Windows 2019 Server version. Instead it comes with a character interface, but with the help of some third party tools you can easily get a fully functional Hyper-V server for free. The following will be assumed: You have a dedicated server connected to a network and you want to install Hyper-V 2019 on this server to run Virtual Machines and/or act as a file server. You have physical access to this server to do the installation. You have another machine connected to the same network to do remote management, running a recent version of Microsoft Windows. You don't want to join a domain or use Active Directory. You can do this if you want to, but this is not included in this post. First you'll need to download the Hyper-V 2019 ISO from  https://www.microsoft.com/en-us/evalcenter/evaluate-hyper-v-server-2019 . You’ll