@@ -27,13 +27,6 @@ const PWM_MAX_VALUE = 1024 # PWM duty cycle range (0-1024)
2727# Global handles for GPIO pins and PWM channels
2828mutable struct HardwareContext
2929 gpio:: GPIO.GPIOController
30- ain1:: GPIO.GPIOPin
31- bin1:: GPIO.GPIOPin
32- stby:: GPIO.GPIOPin
33- ltrans_oe:: GPIO.GPIOPin
34- pwm_chip:: PWM.PWMChip
35- pwm_left:: PWM.PWMChannel
36- pwm_right:: PWM.PWMChannel
3730end
3831
3932"""
@@ -44,13 +37,6 @@ Called on Ctrl-C or program exit.
4437"""
4538function shutdown! (hw:: HardwareContext )
4639 println (Core. stdout , " Shutting down hardware..." )
47- # Stop PWM first
48- PWM. pwmWrite (hw. pwm_left, 0 , PWM_MAX_VALUE)
49- PWM. pwmWrite (hw. pwm_right, 0 , PWM_MAX_VALUE)
50- # Put motor controller into standby
51- GPIO. set_value (hw. stby, 0 )
52- # Disable level translator
53- GPIO. set_value (hw. ltrans_oe, 0 )
5440 println (Core. stdout , " Hardware shutdown complete." )
5541end
5642
@@ -62,99 +48,32 @@ function handle_err(ec)
6248 return
6349end
6450
65-
66- # =============================================================================
67- # Motor Output Functions
68- # =============================================================================
69-
70- """
71- car_stop!(hw::HardwareContext)
72-
73- Stop both motors by setting PWM to 0 and appropriate direction pins.
74- """
75- function car_stop! (hw:: HardwareContext )
76- GPIO. set_value (hw. ain1, 1 ) # HIGH
77- GPIO. set_value (hw. bin1, 0 ) # LOW
78- GPIO. set_value (hw. stby, 1 ) # HIGH (standby off = enabled, but PWM=0)
79- PWM. pwmWrite (hw. pwm_left, 0 , PWM_MAX_VALUE)
80- PWM. pwmWrite (hw. pwm_right, 0 , PWM_MAX_VALUE)
81- end
82-
83- """
84- apply_motor_output!(hw::HardwareContext, pwm_left, pwm_right)
85-
86- Apply PWM signals to motors based on computed control values.
87- Handles direction pin setting based on PWM sign.
88- """
89- function apply_motor_output! (hw:: HardwareContext , pwm_left:: Float32 , pwm_right:: Float32 )
90- # Left motor
91- if pwm_left < 0
92- GPIO. set_value (hw. ain1, 1 )
93- PWM. pwmWrite (hw. pwm_left, round (Int, - pwm_left), PWM_MAX_VALUE)
94- else
95- GPIO. set_value (hw. ain1, 0 )
96- PWM. pwmWrite (hw. pwm_left, round (Int, pwm_left), PWM_MAX_VALUE)
97- end
98-
99- # Right motor
100- if pwm_right < 0
101- GPIO. set_value (hw. bin1, 1 )
102- PWM. pwmWrite (hw. pwm_right, round (Int, - pwm_right), PWM_MAX_VALUE)
103- else
104- GPIO. set_value (hw. bin1, 0 )
105- PWM. pwmWrite (hw. pwm_right, round (Int, pwm_right), PWM_MAX_VALUE)
106- end
107- end
51+ const CM_PRESENT= 23
52+ const D1= 5
53+ const D2= 24
10854
10955function (@main )(args):: Cint
11056 println (Core. stdout , " Balance car starting..." )
11157
11258 # Initialize GPIO controller
11359 gpio = GPIO. open_gpio (" /dev/gpiochip0" )
60+ hw = HardwareContext (gpio)
11461
11562 # Setup GPIO output pins for motor direction
116- ain1 = GPIO. request_output (gpio, AIN1, " motor_ain1" , 0 )
117- bin1 = GPIO. request_output (gpio, BIN1, " motor_bin1" , 0 )
118- stby = GPIO. request_output (gpio, STBY_PIN, " motor_stby" , 0 )
119- ltrans_oe = GPIO. request_output (gpio, LTRANS_OE, " ltrans_oe" , 0 )
63+ cm_present = GPIO. request_output (gpio, CM_PRESENT, " cm_present" , 0 )
64+ d1 = GPIO. request_output (gpio, D1, " d1" , 0 )
65+ d2 = GPIO. request_output (gpio, D2, " d2" , 0 )
12066 println (Core. stdout , " GPIO configured" )
12167
122- # Setup hardware PWM via sysfs
123- pwm_chip = PWM. open_chip (0 )
124-
125- pwm_left = PWM. export_channel_for_gpio (pwm_chip, PWMA_LEFT)
126- PWM. set_period_hz (pwm_left, PWM_FREQ_HZ)
127- PWM. set_duty_cycle_ns (pwm_left, 0 )
128- PWM. enable (pwm_left)
129-
130- pwm_right = PWM. export_channel_for_gpio (pwm_chip, PWMB_RIGHT)
131- PWM. set_period_hz (pwm_right, PWM_FREQ_HZ)
132- PWM. set_duty_cycle_ns (pwm_right, 0 )
133- PWM. enable (pwm_right)
134- println (Core. stdout , " PWM configured" )
135-
136- # Create hardware context
137- hw = HardwareContext (gpio, ain1, bin1, stby, ltrans_oe, pwm_chip, pwm_left, pwm_right)
138-
139- # Initialize IMU (I2C bus 1, address 0x68)
140- imu = MPU6000 (1 , 0x68 )
141- wake! (imu)
142- println (Core. stdout , " IMU initialized" )
143-
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" )
148-
149- # Initialize balance controller
150- ctrl = BalanceController. BalanceController ()
151-
15268 # Enable hardware
153- GPIO. set_value (ltrans_oe, 1 )
154- GPIO. set_value (stby, 1 )
69+ GPIO. set_value (cm_present, 1 )
70+ GPIO. set_value (d1, 1 )
71+ GPIO. set_value (d2, 0 )
72+ d1v = 1
73+ d2v = 0
15574
15675 # Control loop timing (5ms = 200Hz)
157- loop_period_ns = 5_000_000
76+ loop_period_ns = 500_000_000
15877
15978 println (Core. stdout , " Starting control loop..." )
16079 Base. exit_on_sigint (false )
@@ -166,30 +85,10 @@ function (@main)(args)::Cint
16685 wait_until (loop_start + loop_period_ns)
16786 loop_start = time_ns ()
16887
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
187- if isnothing (command)
188- car_stop! (hw)
189- else
190- left, right = command
191- apply_motor_output! (hw, left, right)
192- end
88+ d1v = 1 - d1v
89+ d2v = 1 - d2v
90+ GPIO. set_value (d1, d1v)
91+ GPIO. set_value (d2, d2v)
19392 end
19493 catch e
19594 if e isa InterruptException
0 commit comments