Random bad changes do not read
This commit is contained in:
parent
1f4f39e519
commit
91a32fdd52
|
@ -1,2 +1,3 @@
|
|||
zig-cache/
|
||||
zig-out/
|
||||
*.pdf
|
||||
|
|
12
README.md
12
README.md
|
@ -4,6 +4,12 @@ This creates two main files:
|
|||
* `zig-out/firmware/micromouse.uf2` which can be uploaded to an RP2040.
|
||||
* `zig-out/bin/micromouse` which can be run on the host computer in simulation
|
||||
|
||||
# Simulation
|
||||
Download the mms simulator from https://github.com/mackorone/mms/releases.
|
||||
(I installed this to my Applications folder.)
|
||||
Pop open a new Mouse in the simulator by clicking the plus next to the "Mouse" selector.
|
||||
Point it at this directory. Set it up with `/usr/local/bin/zig build` as the build command and `./zig-out/bin/micromouse` as the run command.
|
||||
|
||||
# Overview / Assumptions
|
||||
We're using the same coordinate space as the simulator (mms). This is "math coords", with 0, 0 in the lower left and positive y up. North is up
|
||||
|
||||
|
@ -19,12 +25,6 @@ TODO: test with non-square mazes. I did my best but I don't know
|
|||
|
||||
Use std.log.debug. microzig. yeah
|
||||
|
||||
# Simulation
|
||||
Download the mms simulator from https://github.com/mackorone/mms/releases.
|
||||
(I installed this to my Applications folder.)
|
||||
Pop open a new Mouse in the simulator by clicking the plus next to the "Mouse" selector.
|
||||
Point it at this directory. Set it up with `/usr/local/bin/zig build` as the build command and `./zig-out/bin/micromouse` as the run command.
|
||||
|
||||
# Sending patches
|
||||
Git is decentralized, which means you don't need an account on Tildegit in order to contribute. Simply clone, make your changes, and commit like normal.
|
||||
|
||||
|
|
|
@ -55,17 +55,24 @@ const Node = struct {
|
|||
return nodes;
|
||||
}
|
||||
|
||||
// Distance from true center (the post in the middle of the 2x2 square) rounded down
|
||||
//
|
||||
fn getCrowDistance(self: *const Node) usize {
|
||||
return self.p.x + self.p.y;
|
||||
}
|
||||
|
||||
pub fn updateScore(self: *Node, newScore: usize) void {
|
||||
// newScore should be less than the current score
|
||||
assert(newScore <= self.score);
|
||||
|
||||
self.score = newScore;
|
||||
// Call updateScore on all adjacent nodes if they have a score which is worse than (newScore + 1)
|
||||
// For some reason BoundedArrays aren't indexable
|
||||
// Call updateScore on all adjacent nodes if they have a score which is worse than (newScore + 100)
|
||||
// For some reason BoundedArrays aren't indexable, hence the .slice()
|
||||
const adjacentNodes = self.getAdjacentNodes().slice();
|
||||
for (adjacentNodes) |node| {
|
||||
if (self.score + 1 < node.score) {
|
||||
node.updateScore(self.score + 1);
|
||||
// 1 square away is a score of 100. This lets us play with tiebreaker metrics
|
||||
if (self.score + 100 < node.score) {
|
||||
node.updateScore(self.score + 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,6 +250,9 @@ pub fn floodFill(dest: []const Point) void {
|
|||
for (adjacentNodes) |n| {
|
||||
std.log.debug("Node at ({}, {}) has score {}", .{ n.p.x, n.p.y, n.score });
|
||||
assert(@TypeOf(n) == *Node);
|
||||
// Replace minAdjacent if this new node is shorter
|
||||
|
||||
//
|
||||
if (minAdjacent == null or n.score < minAdjacent.?.score) {
|
||||
minAdjacent = n;
|
||||
}
|
||||
|
|
47
src/main.zig
47
src/main.zig
|
@ -4,15 +4,52 @@ const algo = @import("algorithm.zig");
|
|||
const robot = algo.robot;
|
||||
const map = @import("map.zig");
|
||||
|
||||
const rp2040 = @import("microzig").hal;
|
||||
// const multicore = rp2040.multicore;
|
||||
|
||||
// TODO: move into algo
|
||||
pub fn alt_core () noreturn {
|
||||
// while true
|
||||
// Flash pin 6 for now
|
||||
while (true) {
|
||||
if (is_robot) {
|
||||
robot.toggle_led_6();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const is_robot = algo.is_robot;
|
||||
// // TODO: Refactor again. algo.is_robot???
|
||||
// if (algo.is_robot) {
|
||||
// alt_core
|
||||
// }
|
||||
|
||||
const time = @import("microzig").hal.time;
|
||||
|
||||
// Entry point for second core
|
||||
fn core1 () noreturn {
|
||||
time.sleep_ms(1000);
|
||||
alt_core();
|
||||
}
|
||||
|
||||
pub fn main() !noreturn {
|
||||
// Power On test
|
||||
|
||||
// TODO: rename is_robot to is_physical or something
|
||||
if (!is_robot) {
|
||||
// TODO: spawn a thread to run alt-core operations
|
||||
}else {
|
||||
// multicore.launch_core1(core1);
|
||||
}
|
||||
|
||||
algo.setup();
|
||||
|
||||
// Flood fill to the goal
|
||||
algo.floodFill(map.goals[0..]);
|
||||
// // Flood fill to the goal
|
||||
// algo.floodFill(map.goals[0..]);
|
||||
|
||||
// Flood fill back to the start
|
||||
const starts = [_]map.Point{ map.start };
|
||||
algo.floodFill(starts[0..]);
|
||||
// // Flood fill back to the start
|
||||
// const starts = [_]map.Point{ map.start };
|
||||
// algo.floodFill(starts[0..]);
|
||||
|
||||
robot.stall();
|
||||
}
|
||||
|
|
|
@ -8,13 +8,193 @@ const map = @import("map.zig");
|
|||
const microzig = @import("microzig");
|
||||
const rp2040 = microzig.hal;
|
||||
const time = rp2040.time;
|
||||
const i2c = rp2040.i2c;
|
||||
const gpio = rp2040.gpio;
|
||||
|
||||
const pin_config = rp2040.pins.GlobalConfiguration {
|
||||
.GPIO25 = .{
|
||||
.name = "onboard_led",
|
||||
.direction = .out,
|
||||
},
|
||||
// TODO: Fill in the rest
|
||||
// 6 colored LEDs
|
||||
.GPIO0 = .{
|
||||
.name = "led_4",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO1 = .{
|
||||
.name = "led_3",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO2 = .{
|
||||
.name = "led_5",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO3 = .{
|
||||
.name = "led_2",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO4 = .{
|
||||
.name = "led_6",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO5 = .{
|
||||
.name = "led_1",
|
||||
.direction = .out,
|
||||
},
|
||||
|
||||
// 3 of the 5 LiDAR clock enable pins
|
||||
// Instead of writing 1 to the CE pins, we should set them as inputs and change them to pull-high
|
||||
// Then we set as an output and write 0
|
||||
// This is because the sensor board is actually running at 1.8V
|
||||
// Each LiDAR has:
|
||||
// GPIO0 - enable pin, must be pulled high during boot and when using the chip, this is our ce pin
|
||||
// SCL
|
||||
// SDA
|
||||
// We don't need to worry about these pins in software, they're wired in!
|
||||
// GPIO1 -
|
||||
// AVDD - needs power second
|
||||
// AVSS_VCSEL
|
||||
// AVDD_VCSEL - needs power first
|
||||
// The config here doesn't really matter because we dynamically update these every time we write to them.
|
||||
.GPIO6 = .{
|
||||
// LCE3
|
||||
.name = "lidar_front_left_ce",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO7 = .{
|
||||
// LCE5
|
||||
.name = "lidar_front_ce",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO8 = .{
|
||||
// LCE1
|
||||
.name = "lidar_back_left_ce",
|
||||
.direction = .out,
|
||||
},
|
||||
|
||||
// Motors
|
||||
.GPIO9 = .{
|
||||
// M/Fault ("indicates an error condition in the motor controller (such as over current)")
|
||||
.name = "motor_fault",
|
||||
.direction = .in,
|
||||
},
|
||||
|
||||
// Motor Right (or B)
|
||||
.GPIO10 = .{
|
||||
// MB2
|
||||
.name = "motor_right_2",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO11 = .{
|
||||
// MB1
|
||||
.name = "motor_right_1",
|
||||
.direction = .out,
|
||||
},
|
||||
// Motor Left (or A)
|
||||
.GPIO12 = .{
|
||||
// MA2
|
||||
.name = "motor_left_2",
|
||||
.direction = .out,
|
||||
},
|
||||
.GPIO13 = .{
|
||||
// MA1
|
||||
.name = "motor_left_1",
|
||||
.direction = .out,
|
||||
},
|
||||
|
||||
// Motor Encoders
|
||||
// Zach recommends triggering a double-edged interrupter on 1 and clocking on 2
|
||||
// You read the second to know if you're going forward or backwards
|
||||
.GPIO14 = .{
|
||||
// MAE2
|
||||
.name = "motor_left_encoder_1",
|
||||
.direction = .in,
|
||||
},
|
||||
.GPIO15 = .{
|
||||
// MAE1
|
||||
.name = "motor_left_encoder_2",
|
||||
.direction = .in,
|
||||
},
|
||||
.GPIO16 = .{
|
||||
// MBE2
|
||||
.name = "motor_right_encoder_2",
|
||||
.direction = .in,
|
||||
},
|
||||
.GPIO17 = .{
|
||||
// MBE1
|
||||
.name = "motor_right_encoder_1",
|
||||
.direction = .in,
|
||||
},
|
||||
|
||||
// Buttons
|
||||
.GPIO18 = .{
|
||||
// BTN1
|
||||
.name = "button_1",
|
||||
.direction = .in,
|
||||
},
|
||||
.GPIO19 = .{
|
||||
// BTN2
|
||||
.name = "button_2",
|
||||
.direction = .in,
|
||||
},
|
||||
|
||||
// SD Card
|
||||
// .GPIO20 = .{
|
||||
// // SD_MISO
|
||||
// .name = "button_2",
|
||||
// .direction = .in,
|
||||
// },
|
||||
// .GPIO21 = .{
|
||||
// // SD_CSB
|
||||
// .name = "button_2",
|
||||
// .direction = .in,
|
||||
// },
|
||||
// .GPIO22 = .{
|
||||
// // SD_CLK
|
||||
// .name = "button_2",
|
||||
// .direction = .in,
|
||||
// },
|
||||
// .GPIO23 = .{
|
||||
// // SD_MOSI
|
||||
// .name = "button_2",
|
||||
// .direction = .in,
|
||||
// },
|
||||
|
||||
// LiDAR signals
|
||||
// These aren't GPIO pins, they're I2C pins, so we don't need to configure them here
|
||||
// .GPIO24 = .{
|
||||
// // SCL
|
||||
// .name = "",
|
||||
// .direction = .out,
|
||||
// },
|
||||
// .GPIO25 = .{ // This is the on board LED on the Pico
|
||||
// // SDA
|
||||
// .name = "",
|
||||
// .direction = .out,
|
||||
// },
|
||||
|
||||
// 2 of the 5 encoders
|
||||
.GPIO26 = .{
|
||||
// LCE2
|
||||
.name = "lidar_back_right_ce",
|
||||
.direction = .out,
|
||||
// .pull =
|
||||
},
|
||||
.GPIO27 = .{
|
||||
// LCE4
|
||||
.name = "lidar_front_right_ce",
|
||||
.direction = .out,
|
||||
},
|
||||
|
||||
// Motor Current monitoring
|
||||
// These pins support Analog-Digital Conversion, which is cool
|
||||
// TODO: What do these do? What do we do with them?
|
||||
.GPIO28 = .{
|
||||
// MAI
|
||||
.name = "ma_i",
|
||||
.direction = .in,
|
||||
},
|
||||
.GPIO29 = .{
|
||||
// MBI
|
||||
.name = "mb_i",
|
||||
.direction = .in,
|
||||
},
|
||||
};
|
||||
// comptime {
|
||||
// @compileLog(@typeInfo(@TypeOf(pin_config.apply)));
|
||||
|
@ -27,13 +207,57 @@ const RIGHT_MOTOR = 2;
|
|||
// 254mm square size
|
||||
const SQUARE_SIZE = 254;
|
||||
|
||||
var pins: rp2040.pins.Pins(pin_config) = undefined;
|
||||
|
||||
pub fn toggle_led_6 () void {
|
||||
// TODO: this does bad things if pins hasn't been defined by the first core yet
|
||||
pins.led_5.toggle();
|
||||
}
|
||||
|
||||
// Zach confirms i2c 0
|
||||
// const i2c0 = i2c.num(0);
|
||||
|
||||
// Pin stuff
|
||||
pub fn setup () void {
|
||||
const pins = pin_config.apply();
|
||||
pins = pin_config.apply();
|
||||
|
||||
pins.onboard_led.toggle();
|
||||
pins.onboard_led.toggle();
|
||||
// const lidar_ce_pins = [_]microzig.hal.gpio.Pin{
|
||||
// pins.lidar_front_left_ce,
|
||||
// pins.lidar_front_right_ce,
|
||||
// pins.lidar_back_right_ce,
|
||||
// pins.lidar_back_left_ce,
|
||||
// pins.lidar_front_ce,
|
||||
// };
|
||||
|
||||
// _ = i2c0.apply(.{
|
||||
// .clock_config = rp2040.clock_config, // Zach says the default here is fine
|
||||
// .scl_pin = gpio.num(24),
|
||||
// .sda_pin = gpio.num(25),
|
||||
// });
|
||||
|
||||
// // We need to setup the LiDAR addresses
|
||||
// // TODO: Create a Lidar struct with methods
|
||||
// // The way we're doing this right now, we are enabling every LiDAR
|
||||
// const LIDAR_ADDR_BASE: i2c.Address = @enumFromInt(0x50);
|
||||
// // Disable all of them
|
||||
// for (lidar_ce_pins) |pin| {
|
||||
// pin.set_direction(.out);
|
||||
// pin.put(0);
|
||||
// }
|
||||
// // One by one, enable and give an address
|
||||
// var current_address = LIDAR_ADDR_BASE;
|
||||
// for (lidar_ce_pins) |pin| {
|
||||
// // Enable
|
||||
// pin.set_direction(.in);
|
||||
// pin.set_pull(.up);
|
||||
// // Write an address
|
||||
// i2c0.set_address(current_address);
|
||||
// current_address = @enumFromInt(@intFromEnum(current_address) + 1);
|
||||
// }
|
||||
|
||||
|
||||
// pins.onboard_led.toggle();
|
||||
// pins.onboard_led.toggle();
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
@ -68,8 +292,46 @@ pub fn readBack() bool {
|
|||
}
|
||||
|
||||
pub fn stall() noreturn {
|
||||
|
||||
pins.motor_right_1.put(1);
|
||||
pins.motor_right_2.put(0);
|
||||
pins.motor_left_1.put(1);
|
||||
pins.motor_left_2.put(0);
|
||||
|
||||
time.sleep_ms(5000);
|
||||
|
||||
pins.motor_right_1.put(0);
|
||||
pins.motor_right_2.put(0);
|
||||
pins.motor_left_1.put(0);
|
||||
pins.motor_left_2.put(0);
|
||||
|
||||
while (true) {
|
||||
// pins.onboard_led.toggle();
|
||||
time.sleep_ms(1000);
|
||||
|
||||
// const b1 = pins.button_1.read();
|
||||
// const b2 = pins.button_2.read();
|
||||
|
||||
// pins.led_1.put(b1);
|
||||
// pins.led_6.put(b2);
|
||||
|
||||
|
||||
|
||||
time.sleep_ms(10);
|
||||
|
||||
|
||||
|
||||
// pins.led_1.put(0);
|
||||
// pins.led_2.put(1);
|
||||
// time.sleep_ms(500);
|
||||
// pins.led_2.put(0);
|
||||
// pins.led_3.put(1);
|
||||
// time.sleep_ms(500);
|
||||
// pins.led_3.put(0);
|
||||
// pins.led_4.put(1);
|
||||
// time.sleep_ms(500);
|
||||
// pins.led_4.put(0);
|
||||
// pins.led_6.put(1);
|
||||
// time.sleep_ms(500);
|
||||
// pins.led_6.put(0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue