"The idea of mucking about in programming is, for better or for worse, not very popular in grown up computer science. Programming these days has become more of an engineering discipline with the idea being that you should do things once and do it right. Logo is and always was about debugging. Before the do it right stage there are always dozens if not hundreds of do it not-quite-right stages. This iterate-iterate-iterate then iterate again is not very prevalent in work with microcontrollers. LightLogo and Arduino Logo try to make microcontroller programming interactive but they are far from the mainstream." Brian Silverman
- A project to get Logo running on these Turtle Robots
- More straightforward programming, not pseudo-Logo inside Arduino code
- Bring physicality to programming
- Bits to Atoms
- Logo needs a comm channel, which the Trinket lacks
- Metro Mini (Adafruit)
- $14.95
- Slightly longer than the Trinket but will still fit onto the existing breadboard
- FTDI Driver
- Mac: Make sure you download and install the latest FTDI driver
- Windows: appears to auto-update
Road Map
- Step 1: Get ArduinoLogo running on the Metro Mini
- URL
- Loading ArduinoLogo onto the Metro using the LightLogo installation.txt as a guide
- Step 2: Prototype outside the turtle
- Arduino
- proto board
- Darlington driver
- Arduino pin can’t supply the voltage, so the Darlington driver acts as an on/off switch, pumps up and out the current
- One stepper motor
- Step 3: Controlling the servo
- Send a pulse every 20 ms, the width of the pulse tells the servo at what degree it should be
- PWM
- Oscilloscope
- Step 4: Use the results to left/right, pen up/down, other movements
Loading VM onto Metro Mini
- Loaded ArduinoLogo on a Sparkfun Red Board and an Uno
- Multimeter: set to V
- black on GND and red 5V: should get about 5 volts
- black on GND and red on pin 2, type on2 and read voltage
- In ArduinoLogo console on computer, Print 1234
- returns 1234 in the console
- running Logo on the Arduino
- Click “download” (test.txt included with ArduinoLogo)
- VM.txt file is the entire development environment
- Extremely small size file versus the Arduino IDE
Updating
- To install updates to ArduinoLogo into the Arduino
1. open the assembler project and start assembler.jar
2. type
wipe<cr>
into the command center
3. click download
4. quit the assembler project
5. download test.txt from Logo.jar
First Demonstration of Stepper Motor
- Mucking Around Breadboard
- Metro Mini
- Darlington chip (notch up)
- inputs are five bottom pins on left
- output is five bottom pins on right
- Stepper wiring: left stepper (looking from breadboard side) uses pins 2-5, right stepper pins 6-9. Each red stepper wire gets Vin from battery, GND is shared from common GND pin on Darlington.
- Male header for stepper
- External battery pack for the motor
- Stepper: turn on and turn off
- step coils in 4 phases
- in testStepper.txt: stepping through the pins in the motor
- phase: which coils to light up
- data sheet: arcane measurements and gearing
- needs unusual arithmetic to get the measurement into a useable form
Turtle Breadboard
- Turtle Breadboard
- The battery needs to be connected to the power pins of the Darlington array.
- I usually use the outermost rail as gnd and the inner one as +5. This is a little unconventional since it isn't consistent with the printed +/- markings. Brian
- The battery needs to power the Darlington array for now and the servo for when we get to it. The Arduino is happy with USB power. Later we can rewire the Arduino to use the battery power so the turtle can run autonomously. Brian
- The notch on the Darlington chip is away from the Metro. Brian
- To power the Metro to run un-tethered:
- Vin goes from battery pack to bottom left Metro pin, labeled USB.
- GND wire from battery pack to GND pin on Metro.
- That's all!
- The power stays "on" for some time after you pull the plug. When the power gets restored it look to the Arduino more like a reset than a powerup. I was able to make this largely go away by putting a 10k resistor between the 5V pin of the arduino and gnd. This drains the residual power. Brian
Light Sensor
- "To use, connect one side of the photo cell (either one, its symmetric) to power (for example 5V) and the other side to your microcontroller's analog input pin. Then connect a 10K pull-down resistor from that analog pin to ground. The voltage on the pin will be 2.5V or higher when its light out and near ground when its dark."
- This doesn't have to take any breadboard space. The light sensor is between a metro pin and a power rail. The resistor is between the same pin and the other power rail.
- If you use the pin marked A0 you should be able to do the following from logo
print a0
or
repeat 100 [print a0 wait 100]
- The light sensor is great! Here's a nice curly design that came from it. The sensor faced the light and as it turned away from the light the curve radius decreased. Erik
to startup
pd wait 1000
let [n a0]
repeat 200 [
arcrt 10 :n
make "n a0
]
pu
alloff
end
Working Within the Turtle
- Erik and Brian moved the turtle movements to sys.txt, so now you are free to program in test.txt.
to startup
square
end
to square
repeat 4 [fd 100 lt 90]
end
- Updated sys.txt. "I also added sensor0-sensor5 as synonyms of a0-a5 as Michael Tempel suggested we do for LightLogo." Brian
global [rpos lpos box1 box2]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; pins
;;
constants
[[pinb $23][ddrb $24][portb $25]
[pind $29][ddrd $2a][portd $2b]
[didr0 $7e][adcsra $7a][admux $7c][adcl $78][adch $79]
[tccr0a $44][tccr0b $45][ocr0a $47][ocr0b $48]
[tccr2a $b0][tccr2b $b1][ocr2b $b4]
[tccr1a $80][tccr1b $81][ocr1al $88][ocr1ah $89][ocr1bl $8a][ocr1bh $8b]]
to pin-init
bsetb ddrd $fc ; pins 2-7 as outputs
bsetb ddrb $0f ; pins 8-11 as outputs
bsetb didr0 $3f ; 6 analog pins
writeb adcsra $86 ; turn on a/d
; pwm on pin 10
writeb ocr1ah byte1 40000 ; 20 msec period
writeb ocr1al byte0 40000
writeb tccr1a $23 ; fast pwm mode
writeb tccr1b $1a ; fast pwm, /8
end
to powerup
pu
setrpos 0
setlpos 0
alloff
end
to setpw :n
writeb ocr1bh byte1 :n
writeb ocr1bl byte0 :n
end
to adread :ch
writeb admux :ch + $40
bsetb adcsra $40
waituntil [not btstb adcsra $40]
output (readb adcl) + (lsh readb adch 8)
end
define a0 [][output adread 0]
define a1 [][output adread 1]
define a2 [][output adread 2]
define a3 [][output adread 3]
define a4 [][output adread 4]
define a5 [][output adread 5]
define sensor0 [][output adread 0]
define sensor1 [][output adread 1]
define sensor2 [][output adread 2]
define sensor3 [][output adread 3]
define sensor4 [][output adread 4]
define sensor5 [][output adread 5]
define on2 [][bsetb portd 4]
define off2 [][bclrb portd 4]
define on3 [][bsetb portd 8]
define off3 [][bclrb portd 8]
define on4 [][bsetb portd $10]
define off4 [][bclrb portd $10]
define on5 [][bsetb portd $20]
define off5 [][bclrb portd $20]
define on6 [][bsetb portd $40]
define off6 [][bclrb portd $40]
define on7 [][bsetb portd $80]
define off7 [][bclrb portd $80]
define on8 [][bsetb portb $01]
define off8 [][bclrb portb $01]
define on9 [][bsetb portb $02]
define off9 [][bclrb portb $02]
define wait [millis][mwait :millis]
define random [from to][output :from + random1 :to - :from + 1]
; servo
to pu
;setpw 2000
setpw 2500
end
to pd
setpw 4500
end
; procedures for driving
to fd :n
repeat :n [rstep+ lstep+]
alloff
end
to bk :n
repeat :n [rstep- lstep-]
alloff
end
to rt :n
make "n :n * 25 / 10
repeat :n [rstep- lstep+]
alloff
end
to lt :n
make "n :n * 25 / 10
repeat :n [rstep+ lstep-]
alloff
end
; control the right motor
to rstep+
setrpos rpos + 1
if rpos > 3 [setrpos 0]
rphase rpos
wait 5
end
to rstep-
setrpos rpos - 1
if rpos < 0 [setrpos 3]
rphase rpos
wait 5
end
to rphase :n
if :n = 0 [on6 off8 on7 off9]
if :n = 1 [off6 on8 on7 off9]
if :n = 2 [off6 on8 off7 on9]
if :n = 3 [on6 off8 off7 on9]
end
; control the left motor
to lstep+
setlpos lpos + 1
if lpos > 3 [setlpos 0]
lphase lpos
wait 5
end
to lstep-
setlpos lpos - 1
if lpos < 0 [setlpos 3]
lphase lpos
wait 5
end
to lphase :n
if :n = 0 [on2 off4 off3 on5]
if :n = 1 [off2 on4 off3 on5]
if :n = 2 [off2 on4 on3 off5]
if :n = 3 [on2 off4 on3 off5]
end
; arc procedures
to arcrt :angle :radius
let [n arcstepcount :angle :radius
lf 1000
rf arcfract :radius]
arcsteps :n :lf :rf
end
to arclt :angle :radius
let [n arcstepcount :angle :radius
lf arcfract :radius
rf 1000]
arcsteps :n :lf :rf
end
to arcstepcount :angle :radius
let [or mulfract :radius * 10 + 1415 6283 10000]
output mulfract :or * 2 :angle 720
end
to arcfract :r
ifelse :r > 141
[output mulfract 1000 :r * 10 - 1415 :r * 10 + 1415]
[output 0 - mulfract 1000 1415 - (:r * 10) :r * 10 + 1415]
end
define mulfract [n num den][output ufmul :n ufdiv :num :den]
to arcsteps :n :lf :rf
let [l 0 r 0]
repeat :n
[make "l :l + :lf
make "r :r + :rf
if :l > 999 [lstep+ make "l :l - 1000]
if :l < -999 [lstep- make "l :l + 1000]
if :r > 999 [rstep+ make "r :r - 1000]
if :r < -999 [rstep- make "r :r + 1000]
]
end
to alloff
off2 off3 off4 off5
off6 off7 off8 off9
end
- This version of test.txt includes support for Brian's arclt and arcrt functions. It also includes previous updates for the servo.
;01-07-16
global [rpos lpos]
to startup
setrpos 0
setlpos 0
alloff
test
end
to test
pd
wait 1000
repeat 10 [
arcrt 360 200
rt 36
]
pu
end
;to test
;draw a square
;repeat 4 [fd 100 lt 90]
;end
;cynthiaAppleLogoSpider
;joshburker010116
;spider
;end
to rightleg
fd 300
rt 90
fd 300
bk 300
lt 90
bk 300
end
to rightside
rt 90
repeat 4 [rightleg lt 20]
lt 10
end
to leftleg
fd 300
lt 90
fd 300
bk 300
rt 90
bk 300
end
to leftside
lt 90
repeat 4 [leftleg rt 20]
rt 10
end
to spider
leftside
rightside
fd 100 bk 100
end
;brian arc
to arcsteps :n :lf :rf
let [l 0
r 0]
repeat :n
[make "l :l + :lf
make "r :r + :rf
if :l > 999 [lstep+ make "l :l - 1000]
if :l < -999 [lstep- make "l :l + 1000]
if :r > 999 [rstep+ make "r :r - 1000]
if :r < -999 [rstep- make "r :r + 1000]]
end
to arcrt :angle :radius
let [n arcstepcount :angle :radius
lf 1000
rf arcfract :radius]
arcsteps :n :lf :rf
end
to arclt :angle :radius
let [n arcstepcount :angle :radius
lf arcfract :radius
rf 1000]
arcsteps :n :lf :rf
end
to arcstepcount :angle :radius
let [or mulfract :radius * 10 + 1415 6283 10000]
output mulfract :or * 2 :angle 720
end
to arcfract :r
ifelse :r > 141
[output mulfract 1000 :r * 10 - 1415 :r * 10 + 1415]
[output 0 - mulfract 1000 1415 - (:r * 10) :r * 10 + 1415]
end
;erik curve
to curve
pd
repeat 4 [
repeat 50 [
repeat 4 [
rstep+
]
lstep-
]
repeat 50 [
repeat 4 [
lstep+
]
rstep-
]
]
pu
end
;erik curves
to curves
pd
let [left 1]
let [right 1]
let [curve 1]
repeat 20 [
make "curve random 50 100
make "left random 1 20
make "right random 1 20
repeat :curve [
repeat :left [
lstep+
]
repeat :right [
rstep-
]
]
make "curve random 50 100
make "left random 1 20
make "right random 1 20
repeat :curve [
repeat :left [
lstep-
]
repeat :right [
rstep+
]
]
]
pu
end
;erik spiral
to spiral
pd
let [stepsr -1000 numsteps 100]
repeat 40 [
arcsteps :numsteps :stepsr 1000
make "stepsr :stepsr + 50
if :stepsr > 600 [
make "numsteps 50
]
]
pu
end
;erik curly
to curly
pd
let [numsteps 100 stepsr -600 stepsl 1000 change 50]
repeat 16 [
arcsteps :numsteps :stepsr :stepsl
make "numsteps :numsteps + :change
make "stepsr :stepsr + 100
make "stepsl :stepsl - 100
if :stepsr > 200 [
make "change -50
]
]
pu
end
;josh recursive spiral routine
to spi :step :angle
fd :step
rt :angle
spi :step + 20 :angle
end
;;;;;;;;;;;;;;;;;;;
;
;original code below
to fd :n
repeat :n [rstep+ lstep+]
alloff
end
to bk :n
repeat :n [rstep- lstep-]
alloff
end
to rt :n
make "n :n * 25 / 10
repeat :n [rstep- lstep+]
alloff
end
to lt :n
make "n :n * 25 / 10
repeat :n [rstep+ lstep-]
alloff
end
; control the right motor
to rstep+
setrpos rpos + 1
if rpos > 3 [setrpos 0]
rphase rpos
wait 5
end
to rstep-
setrpos rpos - 1
if rpos < 0 [setrpos 3]
rphase rpos
wait 5
end
to rphase :n
if :n = 0 [on6 off8 on7 off9]
if :n = 1 [off6 on8 on7 off9]
if :n = 2 [off6 on8 off7 on9]
if :n = 3 [on6 off8 off7 on9]
end
; control the left motor
to lstep+
setlpos lpos + 1
if lpos > 3 [setlpos 0]
lphase lpos
wait 5
end
to lstep-
setlpos lpos - 1
if lpos < 0 [setlpos 3]
lphase lpos
wait 5
end
to lphase :n
if :n = 0 [on2 off4 off3 on5]
if :n = 1 [off2 on4 off3 on5]
if :n = 2 [off2 on4 on3 off5]
if :n = 3 [on2 off4 on3 off5]
end
to alloff
off2 off3 off4 off5
off6 off7 off8 off9
end
to pu
;setpw 1200
setpw 2500
end
to pd
;setpw 5000
setpw 4500
end
- This version of sys.txt includes one change on the last line for the math needed in Brian's arcrt and arclt functions.
global [box1 box2]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; pins
;;
constants
[[pinb $23][ddrb $24][portb $25]
[pind $29][ddrd $2a][portd $2b]
[didr0 $7e][adcsra $7a][admux $7c][adcl $78][adch $79]
[tccr0a $44][tccr0b $45][ocr0a $47][ocr0b $48]
[tccr2a $b0][tccr2b $b1][ocr2b $b4]
[tccr1a $80][tccr1b $81][ocr1al $88][ocr1ah $89][ocr1bl $8a][ocr1bh $8b]]
to pin-init
bsetb ddrd $fc ; pins 2-7 as outputs
bsetb ddrb $0f ; pins 8-11 as outputs
bsetb didr0 $3f ; 6 analog pins
writeb adcsra $86 ; turn on a/d
; pwm on pin 10
writeb ocr1ah byte1 40000 ; 20 msec period
writeb ocr1al byte0 40000
writeb tccr1a $23 ; fast pwm mode
writeb tccr1b $1a ; fast pwm, /8
end
to setpw :n
writeb ocr1bh byte1 :n
writeb ocr1bl byte0 :n
end
to adread :ch
writeb admux :ch + $40
bsetb adcsra $40
waituntil [not btstb adcsra $40]
output (readb adcl) + (lsh readb adch 8)
end
define a0 [][output adread 0]
define a1 [][output adread 1]
define a2 [][output adread 2]
define a3 [][output adread 3]
define a4 [][output adread 4]
define a5 [][output adread 5]
define on2 [][bsetb portd 4]
define off2 [][bclrb portd 4]
define on3 [][bsetb portd 8]
define off3 [][bclrb portd 8]
define on4 [][bsetb portd $10]
define off4 [][bclrb portd $10]
define on5 [][bsetb portd $20]
define off5 [][bclrb portd $20]
define on6 [][bsetb portd $40]
define off6 [][bclrb portd $40]
define on7 [][bsetb portd $80]
define off7 [][bclrb portd $80]
define on8 [][bsetb portb $01]
define off8 [][bclrb portb $01]
define on9 [][bsetb portb $02]
define off9 [][bclrb portb $02]
define wait [millis][mwait :millis]
define random [from to][output :from + random1 :to - :from + 1]
define mulfract [n num den][output ufmul :n ufdiv :num :den]
Mucking Around With Curves
- Here's how to get them, you skip past fd, bk, rt, lt and go straight for rstep+, lstep+, rstep-, and lstep-. Here's an example:
to curve
pd
repeat 4 [
repeat 50 [
repeat 4 [
rstep+
]
lstep-
]
repeat 50 [
repeat 4 [
lstep+
]
rstep-
]
]
pu
end
to curves
pd
let [left 1]
let [right 1]
let [curve 1]
repeat 20 [
make "curve random 50 100
make "left random 1 20
make "right random 1 20
repeat :curve [
repeat :left [
lstep+
]
repeat :right [
rstep-
]
]
make "curve random 50 100
make "left random 1 20
make "right random 1 20
repeat :curve [
repeat :left [
lstep-
]
repeat :right [
rstep+
]
]
]
pu
end
to arcsteps :n :lf :rf
let [l 0
r 0]
repeat :n
[make "l :l + :lf
make "r :r + :rf
if :l > 999 [lstep+ make "l :l - 1000]
if :l < -999 [lstep- make "l :l + 1000]
if :r > 999 [rstep+ make "r :r - 1000]
if :r < -999 [rstep- make "r :r + 1000]]
end
The first input is a number of steps. The second input is a left motor ratio, the third input a right motor ratio. One of the ratios should be 1000 the other somewhat less than 1000.
arcsteps 500 1000 600 should make a right arc.
arcsteps 500 600 1000 should make a left arc.
Negative numbers on both should give back arcs. Negative numbers on one should allow for small circles.
I haven't tested this -- still don't have a turtle and am flying a little blind. If this works we can add a super procedure that takes a radius and an angle and calculates :n, :lf, and :rf. Brian
to spiral
pd
let [stepsr -1000 numsteps 100]
repeat 40 [
arcsteps :numsteps :stepsr 1000
make "stepsr :stepsr + 50
if :stepsr > 600 [
make "numsteps 50
]
]
pu
end
to curly
pd
let [numsteps 100 stepsr -600 stepsl 1000 change 50]
repeat 16 [
arcsteps :numsteps :stepsr :stepsl
make "numsteps :numsteps + :change
make "stepsr :stepsr + 100
make "stepsl :stepsl - 100
if :stepsr > 200 [
make "change -50
]
]
pu
end
Arcs and Angles
- Add to test.txt
;brian arc
to arcsteps :n :lf :rf
let [l 0
r 0]
repeat :n
[make "l :l + :lf
make "r :r + :rf
if :l > 999 [lstep+ make "l :l - 1000]
if :l < -999 [lstep- make "l :l + 1000]
if :r > 999 [rstep+ make "r :r - 1000]
if :r < -999 [rstep- make "r :r + 1000]]
end
to arcrt :angle :radius
let [n arcstepcount :angle :radius
lf 1000
rf arcfract :radius]
arcsteps :n :lf :rf
end
to arclt :angle :radius
let [n arcstepcount :angle :radius
lf arcfract :radius
rf 1000]
arcsteps :n :lf :rf
end
to arcstepcount :angle :radius
let [or mulfract :radius * 10 + 1415 6283 10000]
output mulfract :or * 2 :angle 720
end
to arcfract :r
ifelse :r > 141
[output mulfract 1000 :r * 10 - 1415 :r * 10 + 1415]
[output 0 - mulfract 1000 1415 - (:r * 10) :r * 10 + 1415]
end
- Add to sys.txt
define mulfract [n num den][output ufmul :n ufdiv :num :den]
Beta Release Team
- Tracy
- Erin and high school students
- Brian
- Erik and high school and middle school students
- Josh and middle school students
- Andrew Carle and students
- Colleen Graves and students
- Cynthia Solomon
Taking it Further
20 Things to Do With a Computer
- The idea of Logo and a single output and what can be accomplished
- Logo and one stepper
- Logo and servo
- Computer controlled puppet theatre
Fabricate a PCB
- Users could order the Metro Mini, darlington, pins, power switch, steppers, servo. Solder Metro, darlington, switch into place and the turtle is ready to use with 3D printed parts.
Comments (0)
You don't have permission to comment on this page.