Skip to content

Commit 4a2b2de

Browse files
committed
Get the loop rate right and synchronous I2C
1 parent e3e8c5d commit 4a2b2de

1 file changed

Lines changed: 49 additions & 44 deletions

File tree

deploy/src/main.jl

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -107,26 +107,17 @@ function apply_motor_output!(hw::HardwareContext, pwm_left::Float32, pwm_right::
107107
end
108108

109109
function (@main)(args)::Cint
110-
println(Core.stdout, "hello world!")
110+
println(Core.stdout, "Balance car starting...")
111111

112112
# Initialize GPIO controller
113113
gpio = GPIO.open_gpio("/dev/gpiochip0")
114-
println(Core.stdout, "gpio opened")
115114

116115
# Setup GPIO output pins for motor direction
117116
ain1 = GPIO.request_output(gpio, AIN1, "motor_ain1", 0)
118-
println(Core.stdout, "ain1 configured")
119-
120117
bin1 = GPIO.request_output(gpio, BIN1, "motor_bin1", 0)
121-
println(Core.stdout, "bin1 configured")
122-
123118
stby = GPIO.request_output(gpio, STBY_PIN, "motor_stby", 0)
124-
println(Core.stdout, "stby configured")
125-
126119
ltrans_oe = GPIO.request_output(gpio, LTRANS_OE, "ltrans_oe", 0)
127-
println(Core.stdout, "ltrans_oe configured")
128-
129-
println(Core.stdout, "gpio pins configured")
120+
println(Core.stdout, "GPIO configured")
130121

131122
# Setup hardware PWM via sysfs
132123
pwm_chip = PWM.open_chip(0)
@@ -140,61 +131,75 @@ function (@main)(args)::Cint
140131
PWM.set_period_hz(pwm_right, PWM_FREQ_HZ)
141132
PWM.set_duty_cycle_ns(pwm_right, 0)
142133
PWM.enable(pwm_right)
143-
144-
println(Core.stdout, "pwm startup done")
134+
println(Core.stdout, "PWM configured")
145135

146136
# Create hardware context
147137
hw = HardwareContext(gpio, ain1, bin1, stby, ltrans_oe, pwm_chip, pwm_left, pwm_right)
148138

149-
# Initialize I2C for IMU (bus 1, address 0x68)
139+
# Initialize IMU (I2C bus 1, address 0x68)
150140
imu = MPU6000(1, 0x68)
151-
println(Core.stdout, "i2c startup done")
152-
153141
wake!(imu)
154-
println(Core.stdout, "imu startup done")
142+
println(Core.stdout, "IMU initialized")
155143

156-
timu = ThreadedMPU6000(imu)
157-
tenc_1a = ThreadedEncoder(Encoder(gpio, M1A))
158-
tenc_2a = ThreadedEncoder(Encoder(gpio, M2A))
144+
# Initialize encoders (single-threaded, poll-based)
145+
enc_left = Encoder(gpio, M1A)
146+
enc_right = Encoder(gpio, M2A)
147+
println(Core.stdout, "Encoders initialized")
159148

160-
GPIO.set_value(ltrans_oe, 1)
161-
GPIO.set_value(stby, 1) # take the motor controller out of standby
149+
# Initialize balance controller
162150
ctrl = BalanceController.BalanceController()
163151

164-
ml_update_rate_ns = 50000000
165-
imu_read_margin = 12600000
166-
println(Core.stdout, "start loop!")
167-
start = time_ns()
152+
# Enable hardware
153+
GPIO.set_value(ltrans_oe, 1)
154+
GPIO.set_value(stby, 1)
155+
156+
# Control loop timing (5ms = 200Hz)
157+
loop_period_ns = 5_000_000
158+
159+
println(Core.stdout, "Starting control loop...")
168160
Base.exit_on_sigint(false)
161+
loop_start = time_ns()
162+
169163
try
170164
while true
171-
wait_until(start + ml_update_rate_ns - imu_read_margin)
172-
println(Core.stdout, "wait 1")
173-
put!(timu.request, true) # trigger the IMU request
174-
wait_until(start + ml_update_rate_ns)
175-
println(Core.stdout, "wait 2")
176-
imu_data = take!(timu.response)
177-
println(Core.stdout, "IMU response: $(imu_data.accel_x)")
178-
enc_1_cnts = reset!(tenc_1a)
179-
enc_2_cnts = reset!(tenc_2a)
180-
command = BalanceController.balance_car!(ctrl, enc_1_cnts, enc_2_cnts,
181-
imu_data.accel_x, imu_data.accel_y, imu_data.accel_z,
182-
imu_data.gyro_x, imu_data.gyro_y, imu_data.gyro_z)
183-
start = time_ns()
165+
# Wait for next loop iteration
166+
wait_until(loop_start + loop_period_ns)
167+
loop_start = time_ns()
168+
169+
# Read IMU (synchronous, ~1.3ms at 100kHz SMBus for 14 bytes)
170+
imu_data = read_all_raw(imu)
171+
172+
# Drain encoder events that occurred since last loop
173+
drain_events!(enc_left)
174+
drain_events!(enc_right)
175+
enc_left_cnt = enc_left.count
176+
enc_right_cnt = enc_right.count
177+
reset!(enc_left)
178+
reset!(enc_right)
179+
180+
# Run balance controller
181+
command = BalanceController.balance_car!(ctrl,
182+
enc_left_cnt, enc_right_cnt,
183+
imu_data.accel_x, imu_data.accel_y, imu_data.accel_z,
184+
imu_data.gyro_x, imu_data.gyro_y, imu_data.gyro_z)
185+
186+
# Apply motor output
184187
if isnothing(command)
185188
car_stop!(hw)
186-
println(Core.stdout, "motors stopped!")
187189
else
188190
left, right = command
189191
apply_motor_output!(hw, left, right)
190-
println(Core.stdout, "motors run!")
191192
end
192193
end
193194
catch e
194-
rethrow()
195+
if e isa InterruptException
196+
println(Core.stdout, "\nCtrl-C received")
197+
else
198+
println(Core.stdout, "Error: ", e)
199+
rethrow()
200+
end
195201
finally
196-
GPIO.set_value(ltrans_oe, 0)
197-
GPIO.set_value(stby, 0)
202+
shutdown!(hw)
198203
end
199204
return 0
200205
end

0 commit comments

Comments
 (0)