Index

auto-plow / c95fb77

A wheelchair motor-propelled battery-powered ESP32-driven remote control snow plow.

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
7811 Jan 2020 17:55c95fb77Reverse blade pitch directionJosh Stockin122N

Blob @ auto-plow / main / plow_main.c

text/plain7245 bytesdownload raw
1// plow_main.c
2// Main logic controller for the snow plow
3// Copyright (c) Joshua 'joshuas3' Stockin 2020
4
5#include "plow_main.h"
6#include "pulseIn.h"
7#include "util.h"
8
9#include <stdio.h>
10
11#include "esp_system.h"
12#include "esp_task_wdt.h"
13#include "freertos/FreeRTOS.h"
14#include "freertos/task.h"
15#include "driver/gpio.h"
16#include "driver/uart.h"
17
18static void onrestart(void) {
19 gpio_set_level(STATUS_RED, HIGH);
20 delay(250);
21}
22
23static int ping_count = 1;
24static void pingTask(void * pingOK) {
25 configASSERT(((bool)pingOK) == true);
26 static int beeps;
27 static int i;
28 for (;;) {
29 delay(3000);
30 printf("ping #%dx%d: %i ticks\n", ++beeps, ping_count, xTaskGetTickCount());
31 for (i = 0; i < ping_count; i++) {
32 gpio_set_level(STATUS_YELLOW, HIGH);
33 delay(0200);
34 gpio_set_level(STATUS_YELLOW, LOW);
35 delay(0200);
36 }
37 }
38}
39
40const int uart_blade_control = UART_NUM_1;
41const int uart_motor_control = UART_NUM_2;
42static void radioTask(void * arg) {
43 configASSERT(((bool)arg) == true);
44 unsigned int R1;
45 unsigned int R2;
46 unsigned int R3;
47 unsigned int R4;
48 unsigned int R5;
49 unsigned int R6;
50 unsigned char SWITCH_MOTORS = 0;
51 unsigned char SWITCH_SALT = 0;
52 for (;;) {
53 R1 = pulseIn(RADIO_1, true);
54 R2 = pulseIn(RADIO_2, true);
55 R3 = pulseIn(RADIO_3, true);
56 R4 = pulseIn(RADIO_4, true);
57 R5 = pulseIn(RADIO_5, true);
58 R6 = pulseIn(RADIO_6, true);
59 if (R1 || R2 || R3 || R4 || R5 || R6) {
60 ping_count = 2;
61 unsigned int R1m = map(R1, 160000, 320000, 0, 1000); // right horizontal
62 unsigned int R2m = map(R2, 160000, 320000, 0, 1000); // right vertical
63 unsigned int R3m = map(R3, 160000, 320000, 0, 1000); // left vertical
64 unsigned int R4m = map(R4, 160000, 320000, 0, 1000); // left horizontal
65 unsigned char R5m = map(R5, 160000, 320000, 0, 1000)>500;
66 unsigned char R6m = map(R6, 160000, 320000, 0, 1000)>500;
67
68 // Switches
69 if (SWITCH_SALT != R6m) {
70 printf("salt spreader switch flip\n");
71 SWITCH_SALT = R6m;
72 gpio_set_level(SOLENOID_SALT, !R6m);
73 }
74 if (SWITCH_MOTORS != R5m) {
75 printf("motors switch flip\n");
76 SWITCH_MOTORS = R5m;
77 if (R5m) {
78 gpio_set_level(BATTERY_MOTORCONTROL, !R5m);
79 gpio_set_level(BATTERY_BLADECONTROL, !R5m);
80 delay(200);
81 gpio_set_level(SOLENOID_MOTORS, !R5m);
82 } else {
83 gpio_set_level(SOLENOID_MOTORS, !R5m);
84 delay(200);
85 gpio_set_level(BATTERY_MOTORCONTROL, !R5m);
86 gpio_set_level(BATTERY_BLADECONTROL, !R5m);
87 }
88 }
89
90 // Motor controller configuration
91 if (R5m) {
92 // Blade control
93 unsigned int blade_pitch = 0;
94 unsigned int blade_yaw = 0;
95 if (R3m > 600) {
96 blade_pitch = 192 - map(R3m, 600, 1000, 1, 63);
97 } else if (R3m < 400) {
98 blade_pitch = 192 + (64 - map(R3m, 0, 400, 1, 63));
99 } else {
100 blade_pitch = 192;
101 }
102 if (R4m > 600) {
103 blade_yaw = map(R4m, 600, 1000, 64, 127);
104 } else if (R4m < 400) {
105 blade_yaw = map(R4m, 0, 400, 1, 64);
106 } else {
107 blade_yaw = 64;
108 }
109
110 // Motor control
111 unsigned char motor_left = 0;
112 unsigned char motor_right = 0;
113 if (R2m > 600) {
114 motor_left = map(R2m, 600, 1000, 64, 127);
115 motor_right = map(R2m, 600, 1000, 192, 255);
116 } else if (R2m < 400) {
117 motor_left = map(R2m, 0, 400, 1, 64);
118 motor_right = map(R2m, 0, 400, 128, 192);
119 } else {
120 motor_left = 64;
121 motor_right = 192;
122 }
123 if (R1m > 600) { // right turn
124 motor_left = 64 + map(R1m, 600, 1000, 1, 63);
125 motor_right = 192 - map(R1m, 600, 1000, 1, 63);
126 } else if (R1m < 400) { // left turn
127 motor_left = map(R1m, 0, 400, 1, 63);
128 motor_right = 192 + (64 - map(R1m, 0, 400, 1, 63));
129 }
130 printf("Motors:\tpitch\tyaw\tleft\tright\n");
131 printf("Motors:\t%i\t%i\t%i\t%i\n", blade_pitch, blade_yaw, motor_left, motor_right);
132 char motor_bytes[] = {motor_left, motor_right};
133 char blade_bytes[] = {blade_pitch, blade_yaw};
134 uart_write_bytes(uart_motor_control, (const char*)motor_bytes, 2);
135 uart_write_bytes(uart_blade_control, (const char*)blade_bytes, 2);
136 } else {
137 printf("Radio RX:\t%i\t%i\t%i\t%i\t%i\t%i\n", R1m, R2m, R3m, R4m, R5m, R6m);
138 }
139 } else {
140 ping_count = 1;
141 printf("Radio RX:\t-\t-\t-\t-\t-\t-\n");
142 if (SWITCH_SALT != 0) {
143 printf("salt spreader switch flip\n");
144 SWITCH_SALT = 0;
145 gpio_set_level(SOLENOID_SALT, HIGH);
146 }
147 if (SWITCH_MOTORS != 0) {
148 printf("motors switch flip\n");
149 SWITCH_MOTORS = 0;
150 gpio_set_level(SOLENOID_MOTORS, HIGH);
151 delay(200);
152 gpio_set_level(BATTERY_MOTORCONTROL, HIGH);
153 gpio_set_level(BATTERY_BLADECONTROL, HIGH);
154 }
155 }
156 esp_task_wdt_reset();
157 delay(10);
158 }
159}
160
161void app_main(void)
162{
163 printf("entering app_main\n");
164
165 printf("configuring STATUS_[GREEN|YELLOW|RED] GPIO output\n");
166 gpio_config_t io_conf;
167 io_conf.pin_bit_mask = (1ULL<<STATUS_GREEN) | (1ULL<<STATUS_YELLOW) | (1ULL<<STATUS_RED);
168 io_conf.mode = GPIO_MODE_OUTPUT;
169 io_conf.intr_type = GPIO_INTR_DISABLE;
170 gpio_config(&io_conf);
171
172 printf("pulling STATUS_[GREEN|YELLOW|RED] HIGH\n");
173 gpio_set_level(STATUS_GREEN, HIGH);
174 gpio_set_level(STATUS_YELLOW, HIGH);
175 gpio_set_level(STATUS_RED, HIGH);
176
177 printf("configuring BATTERY_[MOTOR|BLADE]CONTROL, SOLENOID_[SALT|MOTORS], and RELAY_BOARD GPIO output\n");
178 io_conf.pin_bit_mask = (1ULL<<SOLENOID_SALT) | (1ULL<<SOLENOID_MOTORS) | (1ULL<<BATTERY_MOTORCONTROL) | (1ULL<<BATTERY_BLADECONTROL) | (1ULL<<RELAY_BOARD);
179 io_conf.mode = GPIO_MODE_OUTPUT;
180 gpio_config(&io_conf);
181
182 printf("pulling all high\n");
183 gpio_set_level(SOLENOID_SALT, HIGH);
184 gpio_set_level(SOLENOID_MOTORS, HIGH);
185 gpio_set_level(BATTERY_MOTORCONTROL, HIGH);
186 gpio_set_level(BATTERY_BLADECONTROL, HIGH);
187 gpio_set_level(RELAY_BOARD, HIGH);
188
189 printf("configuring RADIO_[1-6] GPIO input\n");
190 io_conf.pin_bit_mask = (1ULL<<RADIO_1) | (1ULL<<RADIO_2) | (1ULL<<RADIO_3) | (1ULL<<RADIO_4) | (1ULL<<RADIO_5) | (1ULL<<RADIO_6);
191 io_conf.mode = GPIO_MODE_INPUT;
192 gpio_config(&io_conf);
193
194 printf("configuring UART\n");
195 uart_config_t uart_config = {
196 .baud_rate = CONTROL_BAUDRATE,
197 .data_bits = UART_DATA_8_BITS,
198 .parity = UART_PARITY_DISABLE,
199 };
200 ESP_ERROR_CHECK(uart_param_config(uart_motor_control, &uart_config));
201 ESP_ERROR_CHECK(uart_param_config(uart_blade_control, &uart_config));
202 ESP_ERROR_CHECK(uart_set_pin(uart_motor_control, UART_MOTOR_CONTROL, NULL_PIN, NULL_PIN, NULL_PIN));
203 ESP_ERROR_CHECK(uart_set_pin(uart_blade_control, UART_BLADE_CONTROL, NULL_PIN, NULL_PIN, NULL_PIN));
204
205 printf("installing UART\n");
206 const int uart_buffer_size = 256;
207 ESP_ERROR_CHECK(uart_driver_install(uart_motor_control, uart_buffer_size, uart_buffer_size, 0, NULL, 0));
208 ESP_ERROR_CHECK(uart_driver_install(uart_blade_control, uart_buffer_size, uart_buffer_size, 0, NULL, 0));
209
210 printf("registering shutdown function\n");
211 esp_register_shutdown_handler(onrestart);
212
213 printf("creating ping task\n");
214 TaskHandle_t pingTaskHandle = NULL;
215 xTaskCreate(pingTask, "pingTask", 2000, (void *)true, tskIDLE_PRIORITY, &pingTaskHandle);
216
217 printf("creating radio task\n");
218 TaskHandle_t radioTaskHandle = NULL;
219 xTaskCreate(radioTask, "radioTask", 10000, (void *)true, 1, &radioTaskHandle);
220
221 printf("pulling STATUS_[YELLOW|RED] LOW\n");
222 gpio_set_level(STATUS_YELLOW, LOW);
223 gpio_set_level(STATUS_RED, LOW);
224}
225