1- using PiGPIO
1+ using WiringPi
22using Timers
33include (joinpath (@__DIR__ , " mpu6000.jl" ))
44include (joinpath (@__DIR__ , " encoder.jl" ))
55
6- module BalanceController
6+ module BalanceController
77include (joinpath (@__DIR__ , " balance_original.jl" ))
88end
99
@@ -16,9 +16,11 @@ const PWMB_RIGHT = 18 # both have hardware PWM
1616const LTRANS_OE = 11 # enables the 3.3V <-> 5V level translator
1717const STBY_PIN = 0
1818
19+ const PWM_RANGE = 1024 # Hardware PWM duty cycle range (0-1024)
20+
1921function handle_err (ec)
2022 if ec == 0
21- return
23+ return
2224 end
2325 println (Core. stdout , " Had error " , ec)
2426 return
3436
3537Stop both motors by setting PWM to 0 and appropriate direction pins.
3638"""
37- function car_stop! (p :: Pi )
38- write (p, AIN1, 1 ) # HIGH
39- write (p, BIN1, 0 ) # LOW
40- write (p, STBY_PIN, 1 ) # HIGH ( standby off = enabled, but PWM=0)
41- PiGPIO . set_PWM_dutycycle (p, PWMA_LEFT, 0 )
42- PiGPIO . set_PWM_dutycycle (p, PWMB_RIGHT, 0 )
39+ function car_stop! ()
40+ digitalWrite ( AIN1, HIGH)
41+ digitalWrite ( BIN1, LOW)
42+ digitalWrite ( STBY_PIN, HIGH ) # standby off = enabled, but PWM=0
43+ pwmWrite ( PWMA_LEFT, 0 )
44+ pwmWrite ( PWMB_RIGHT, 0 )
4345end
4446
4547"""
4850Apply PWM signals to motors based on computed control values.
4951Handles direction pin setting based on PWM sign.
5052"""
51- function apply_motor_output! (p :: Pi , pwm_left:: Float32 , pwm_right:: Float32 )
53+ function apply_motor_output! (pwm_left:: Float32 , pwm_right:: Float32 )
5254 # Left motor
5355 if pwm_left < 0
54- write (p, AIN1, 1 )
55- PiGPIO . set_PWM_dutycycle (p, PWMA_LEFT, round (Int, - pwm_left))
56+ digitalWrite ( AIN1, HIGH )
57+ pwmWrite ( PWMA_LEFT, round (Int, - pwm_left))
5658 else
57- write (p, AIN1, 0 )
58- PiGPIO . set_PWM_dutycycle (p, PWMA_LEFT, round (Int, pwm_left))
59+ digitalWrite ( AIN1, LOW )
60+ pwmWrite ( PWMA_LEFT, round (Int, pwm_left))
5961 end
6062
6163 # Right motor
6264 if pwm_right < 0
63- write (p, BIN1, 1 )
64- PiGPIO . set_PWM_dutycycle (p, PWMB_RIGHT, round (Int, - pwm_right))
65+ digitalWrite ( BIN1, HIGH )
66+ pwmWrite ( PWMB_RIGHT, round (Int, - pwm_right))
6567 else
66- write (p, BIN1, 0 )
67- PiGPIO . set_PWM_dutycycle (p, PWMB_RIGHT, round (Int, pwm_right))
68+ digitalWrite ( BIN1, LOW )
69+ pwmWrite ( PWMB_RIGHT, round (Int, pwm_right))
6870 end
6971end
7072
7173function (@main )(args):: Cint
7274 println (Core. stdout , " hello world!" )
73- p = Pi ()
74- println (Core. stdout , " pi startup done" )
75- PiGPIO. set_internals (p, 8 , 0 )
76- println (Core. stdout , " set debug level" )
77- handle_err (PiGPIO. hardware_PWM (p, PWMA_LEFT, 1000 , 0 ))
78- handle_err (PiGPIO. hardware_PWM (p, PWMB_RIGHT, 1000 , 0 )) # use 1kHz pwm for the motor drivers
75+
76+ # Initialize WiringPi with BCM GPIO numbering
77+ wiringPiSetupGpio ()
78+ println (Core. stdout , " wiringPi startup done" )
79+
80+ # Setup GPIO pins as outputs
81+ pinMode (AIN1, OUTPUT)
82+ pinMode (BIN1, OUTPUT)
83+ pinMode (STBY_PIN, OUTPUT)
84+ pinMode (M1A, INPUT)
85+ pinMode (M2A, INPUT)
86+
87+ # Setup hardware PWM on motor pins
88+ pinMode (PWMA_LEFT, PWM_OUTPUT)
89+ pinMode (PWMB_RIGHT, PWM_OUTPUT)
90+ pwmSetMode (PWM_MODE_MS) # Mark-space mode for motor control
91+ pwmSetRange (PWM_RANGE)
92+ pwmSetClock (19 ) # ~1kHz PWM frequency (19.2MHz / 19 / 1024 ≈ 1kHz)
7993 println (Core. stdout , " pwm startup done" )
80- imu_bus = PiGPIO. i2c_open (p, 1 , 0x68 )
94+
95+ # Initialize I2C for IMU (address 0x68)
96+ imu_handle = wiringPiI2CSetup (0x68 )
97+ if imu_handle < 0
98+ println (Core. stdout , " Failed to initialize I2C" )
99+ return 1
100+ end
81101 println (Core. stdout , " i2c startup done" )
82- imu = MPU6000 (p, imu_bus, GyroRange. GYRO_FS_250, AccelRange. ACCEL_F_2G)
102+
103+ imu = MPU6000 (imu_handle, GyroRange. GYRO_FS_250, AccelRange. ACCEL_F_2G)
83104 wake! (imu)
84105 println (Core. stdout , " imu startup done" )
85106 timu = ThreadedMPU6000 (imu)
86- tenc_1a = ThreadedEncoder (Encoder (p, M1A), 1_000 )
87- tenc_2a = ThreadedEncoder (Encoder (p, M2A), 1_000 )
107+ tenc_1a = ThreadedEncoder (Encoder (M1A), 1_000 )
108+ tenc_2a = ThreadedEncoder (Encoder (M2A), 1_000 )
88109
89110 ctrl = BalanceController ()
90111
91112 ml_update_rate_ns = 50000000
92113 imu_read_margin = 12600000
93114 println (Core. stdout , " start loop!" )
94115 now = time_ns ()
95- while true
116+ while true
96117 wait_until (start + ml_update_rate_ns - imu_read_margin)
97118 put! (timu. request, true ) # trigger the IMU request
98119 wait_until (start + ml_update_rate_ns)
@@ -104,10 +125,10 @@ function (@main)(args)::Cint
104125 imu_data. gyro_x, imu_data. gyro_y, imu_data. gyro_z)
105126 now = time_ns ()
106127 if isnothing (command)
107- car_stop! (p )
108- else
128+ car_stop! ()
129+ else
109130 left, right = command
110- apply_motor_output! (p, left, right)
131+ apply_motor_output! (left, right)
111132 end
112133 end
113134 return 0
169190 readcb_specialized (stream_unknown_type, Int (nread), UInt (nrequested))
170191 nothing
171192 end
172- end
193+ end
0 commit comments