AIK3NJJOAMB2QEYWLVK7B3E4ZMVGPBPPPZD2TGEBZCNM4Y6KI2XQC IPLSYOCQIAQLB6HXL6YBJ5ZKKESCSRO7S7P5SF6I367M6HEJJRNQC TXSGLYOVYQ77EG23PAVW62MBJRHS2WTVAVNQ3NYVBDGKNMSYS7DAC RIKRRTK5ZNVTCDJBS2O54P36TSQXENEZ2DYXJ3WPFW7ZQ6CF4DMQC GSIKHOXLB6QJELAYIGDFLRIG6DRIQFMZG6ZCQ54BNB7FIDBVI5PAC 6GJR2V3AYCEJWLBP2KMTWUNO332MG5OFEUNPCNSSNF5BJKXA3VTQC UAB3QWX6I6PF4BRKRV6C7QKQMEYESRIALOFSOP3P5NAX2SHXABTQC TKNYDMLX6VQSCEFDUY6VTMJPSOEOSWVC3YLDHHD7R4K4RVP3I7KAC KIS6Z2AJQC7NOS2NAATBHNSM5G336VCPQKAZ6O5ALPNL7SSCBWDQC const std = @import("std");const microzig = @import("microzig");const rp2xxx = microzig.hal;const main = @import("main.zig");const log = std.log.scoped(.motor);pub const MotorDriverType = enum {l293,bdr6133,};pub fn MotorDriver(comptime driver: MotorDriverType) type {switch (driver) {.l293 => return L293,.bdr6133 => return BDR6133,}}const L293 = struct {fwd: rp2xxx.gpio.Pin,bwd: rp2xxx.gpio.Pin,speed: rp2xxx.pwm.Pwm,fn stop(self: @This()) void {self.fwd.put(1);self.bwd.put(1);log.debug("Motor stopped", .{});}fn freerun(self: @This()) void {self.speed.set_level(0);log.debug("Motor in freerun mode", .{});}fn forward(self: @This(), level: u16) void {self.fwd.put(1);self.bwd.put(0);self.speed.set_level(level);log.debug("Motor is moving forward: {d}", .{level});}};const BDR6133 = struct {};pub fn tester(comptime driver: MotorDriverType) !void {const md = MotorDriver(driver){.fwd = main.pins.mot1,.bwd = main.pins.mot2,.speed = main.pins.speed,};const pwm_period = 125_000_000 / (@as(usize, main.cv.PWM_period) * 100 + 10_000);var level: usize = pwm_period * 65 / 100;while (level < pwm_period) : (level += pwm_period / 50) {md.forward(@truncate(level));rp2xxx.time.sleep_ms(2000);{ // Measure Back-EMF// Prepare ADCrp2xxx.adc.apply(.{.sample_frequency = null,.round_robin = null,.temp_sensor_enabled = false,.fifo = .{ .dreq_enabled = false, .irq_enabled = false, .shift = false },}); // apply calls enablerp2xxx.adc.select_input(main.pins.m1emf);// Switch to free running modemd.freerun();rp2xxx.time.sleep_us(100);// Actual measurringconst emf = main.cv.manufacturer.emf;rp2xxx.adc.start(.free_running);var emfs: [std.math.maxInt(u8)]u12 = undefined;for (0..emf.iterations) |i| {if (rp2xxx.adc.fifo.has_overflowed()) {std.log.debug("ADC overflow, clearing...", .{});rp2xxx.adc.fifo.clear_overflowed();}while (rp2xxx.adc.fifo.is_empty()) {asm volatile ("" ::: "memory");}emfs[i] = try rp2xxx.adc.fifo.pop();// TODO: check if we should sort right here}// Measuring done, switch the motor back onrp2xxx.adc.set_enabled(false);md.forward(@truncate(level));// std.log.debug("Raw EMF values: {any}", .{emfs});// Sort results, so we can cut out the low and high partstd.sort.pdq(u12, emfs[0..emf.iterations], {}, less);// Calculate average EMFvar sum: u32 = 0;for (emf.low_cutoff..emf.iterations - emf.high_cutoff) |i| {sum += emfs[i];}const m1emf = sum / (emf.iterations - emf.low_cutoff - emf.high_cutoff);std.log.debug("Motor1 average EMF: {d}", .{m1emf});}}}fn less(_: void, a: u12, b: u12) bool {return a < b;}
{ // Motor stuffconst PWM_WRAP = 125_000_000 / (150 * 100 + 10_000) - 1; // 125MHz -> 25kHzconst EMF_ARRAY_SIZE = 100;const EMF_CUTOUT = 15;// TODO: max output is wrap+1 (5000)// minimum: core1.c: get_initial_levelpins.speed.slice().set_wrap(PWM_WRAP);pins.speed.slice().enable();pins.speed.slice().set_phase_correct(false);// pins.speed.slice().set_clk_div(1, 0);// stoppins.mot1.put(1);pins.mot2.put(1);std.log.debug("Motor stopped for {d} ms", .{1000});rp2xxx.time.sleep_ms(1000);pins.mot1.put(1);pins.mot2.put(0);// startvar level: usize = PWM_WRAP / 2;while (level < PWM_WRAP) : (level += 100) {pins.speed.set_level(@truncate(level));rp2xxx.time.sleep_ms(2000);{ // Measure Back-EMF// Prepare ADCrp2xxx.adc.apply(.{.sample_frequency = null,.round_robin = null,.temp_sensor_enabled = false,.fifo = .{ .dreq_enabled = false, .irq_enabled = false, .shift = false },}); // apply calls enablerp2xxx.adc.select_input(pins.m1emf);
// Actual measurringrp2xxx.adc.start(.free_running);var emfs: [EMF_ARRAY_SIZE]u12 = undefined;for (0..EMF_ARRAY_SIZE) |i| {if (rp2xxx.adc.fifo.has_overflowed()) {std.log.debug("ADC overflow, clearing...", .{});rp2xxx.adc.fifo.clear_overflowed();}while (rp2xxx.adc.fifo.is_empty()) {asm volatile ("" ::: "memory");}emfs[i] = try rp2xxx.adc.fifo.pop();// TODO: check if we should sort right here}
// 125MHz -> 25kHzpins.speed.slice().set_wrap(@intCast(125_000_000 / (@as(u32, cv.PWM_period) * 100 + 10_000) - 1));pins.speed.slice().enable();pins.speed.slice().set_phase_correct(false);pins.speed.slice().set_clk_div(1, 0);
// Measuring done, switch the motor back onrp2xxx.adc.set_enabled(false);pins.speed.set_level(@truncate(level));// std.log.debug("Raw EMF values: {any}", .{emfs});// Sort results, so we can cut out the low and high partstd.sort.pdq(u12, &emfs, {}, less);
// try motor.tester(board.motor_driver);
// Calculate average EMFvar sum: u32 = 0;for (EMF_CUTOUT..EMF_ARRAY_SIZE - EMF_CUTOUT) |i| {sum += emfs[i];}const m1emf = sum / (EMF_ARRAY_SIZE - 2 * EMF_CUTOUT);std.log.info("Motor1 average EMF: {d}", .{m1emf});}}}
const BackEMF = packed struct {iterations: u8 = 100, // Number of measurements to calculate Back-EMFdelay_us: u8 = 100, // Delay before measurement startlow_cutoff: u8 = 15, // Number of discarded elements on the low sidehigh_cutoff: u8 = 15, // Number of discarded elements on the high side};