Index

auto-plow / 086937a

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
8007 Sep 2020 18:1622d39c4Retab source filesJosh Stockin1198198G

Blob @ auto-plow / main / plow_main.c

text/plain8930 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(500);
81 gpio_set_level(SOLENOID_MOTORS, !R5m);
82 } else {
83 gpio_set_level(SOLENOID_MOTORS, !R5m);
84 delay(500);
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 = 192;
94 unsigned int blade_yaw = 64;
95 if (R3m > 600) {
96 blade_pitch -= map(R3m, 600, 1000, 1, 63);
97 } else if (R3m < 400) {
98 blade_pitch += (64 - map(R3m, 0, 400, 1, 63));
99 }
100 if (R4m > 600) {
101 blade_yaw = map(R4m, 600, 1000, 64, 127);
102 } else if (R4m < 400) {
103 blade_yaw = map(R4m, 0, 400, 1, 64);
104 }
105
106 // Motor control
107 short motor_left = 64;
108 short motor_right = 192;
109 if (R2m > 600) {
110 motor_left = map(R2m, 600, 1000, 64, 127);
111 motor_right = map(R2m, 600, 1000, 192, 255);
112 } else if (R2m < 400) {
113 motor_left = map(R2m, 0, 400, 1, 64);
114 motor_right = map(R2m, 0, 400, 128, 192);
115 }
116 if (R1m > 600) { // right turn
117 motor_left += map(R1m, 600, 1000, 1, 63);
118 motor_right -= map(R1m, 600, 1000, 1, 63);
119 } else if (R1m < 400) { // left turn
120 motor_left -= (64 - map(R1m, 0, 400, 1, 63));
121 motor_right += (64 - map(R1m, 0, 400, 1, 63));
122 }
123
124 // Constrain motor signals
125 if (motor_left < 1) motor_left = 1;
126 if (motor_left > 127) motor_left = 127;
127 if (motor_right < 128) motor_right = 128;
128 if (motor_right > 255) motor_right = 255;
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
133 char motor_bytes[] = {motor_left, motor_right};
134 uart_write_bytes(uart_motor_control, (const char*)motor_bytes, 2);
135
136 char blade_bytes[] = {blade_pitch, blade_yaw};
137 uart_write_bytes(uart_blade_control, (const char*)blade_bytes, 2);
138 } else {
139 printf("Radio RX:\t%i\t%i\t%i\t%i\t%i\t%i\n", R1m, R2m, R3m, R4m, R5m, R6m);
140 }
141 } else {
142 ping_count = 1;
143 printf("Radio RX:\t-\t-\t-\t-\t-\t-\n");
144 if (SWITCH_SALT != 0) {
145 printf("salt spreader switch flip\n");
146 SWITCH_SALT = 0;
147 gpio_set_level(SOLENOID_SALT, HIGH);
148 }
149 if (SWITCH_MOTORS != 0) {
150 printf("motors switch flip\n");
151 SWITCH_MOTORS = 0;
152 gpio_set_level(SOLENOID_MOTORS, HIGH);
153 delay(200);
154 gpio_set_level(BATTERY_MOTORCONTROL, HIGH);
155 gpio_set_level(BATTERY_BLADECONTROL, HIGH);
156 }
157 }
158 esp_task_wdt_reset();
159 delay(10);
160 }
161}
162
163void app_main(void)
164{
165 printf("entering app_main\n");
166
167 printf("configuring STATUS_[GREEN|YELLOW|RED] GPIO output\n");
168 gpio_config_t io_conf;
169 io_conf.pin_bit_mask = (1ULL<<STATUS_GREEN) | (1ULL<<STATUS_YELLOW) | (1ULL<<STATUS_RED);
170 io_conf.mode = GPIO_MODE_OUTPUT;
171 io_conf.intr_type = GPIO_INTR_DISABLE;
172 gpio_config(&io_conf);
173
174 printf("pulling STATUS_[GREEN|YELLOW|RED] HIGH\n");
175 gpio_set_level(STATUS_GREEN, HIGH);
176 gpio_set_level(STATUS_YELLOW, HIGH);
177 gpio_set_level(STATUS_RED, HIGH);
178
179 printf("configuring BATTERY_[MOTOR|BLADE]CONTROL, SOLENOID_[SALT|MOTORS], and RELAY_BOARD GPIO output\n");
180 io_conf.pin_bit_mask = (1ULL<<SOLENOID_SALT) | (1ULL<<SOLENOID_MOTORS) | (1ULL<<BATTERY_MOTORCONTROL) | (1ULL<<BATTERY_BLADECONTROL) | (1ULL<<RELAY_BOARD);
181 io_conf.mode = GPIO_MODE_OUTPUT;
182 gpio_config(&io_conf);
183
184 printf("pulling all high\n");
185 gpio_set_level(SOLENOID_SALT, HIGH);
186 gpio_set_level(SOLENOID_MOTORS, HIGH);
187 gpio_set_level(BATTERY_MOTORCONTROL, HIGH);
188 gpio_set_level(BATTERY_BLADECONTROL, HIGH);
189 gpio_set_level(RELAY_BOARD, HIGH);
190
191 printf("configuring RADIO_[1-6] GPIO input\n");
192 io_conf.pin_bit_mask = (1ULL<<RADIO_1) | (1ULL<<RADIO_2) | (1ULL<<RADIO_3) | (1ULL<<RADIO_4) | (1ULL<<RADIO_5) | (1ULL<<RADIO_6);
193 io_conf.mode = GPIO_MODE_INPUT;
194 gpio_config(&io_conf);
195
196 printf("configuring UART\n");
197 uart_config_t uart_config = {
198 .baud_rate = CONTROL_BAUDRATE,
199 .data_bits = UART_DATA_8_BITS,
200 .parity = UART_PARITY_DISABLE,
201 .stop_bits = UART_STOP_BITS_1,
202 .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
203 };
204 ESP_ERROR_CHECK(uart_param_config(uart_motor_control, &uart_config));
205 ESP_ERROR_CHECK(uart_param_config(uart_blade_control, &uart_config));
206 ESP_ERROR_CHECK(uart_set_pin(uart_motor_control, UART_MOTOR_CONTROL, NULL_PIN, NULL_PIN, NULL_PIN));
207 ESP_ERROR_CHECK(uart_set_pin(uart_blade_control, UART_BLADE_CONTROL, NULL_PIN, NULL_PIN, NULL_PIN));
208
209 printf("installing UART\n");
210 const int uart_buffer_size = 256;
211 ESP_ERROR_CHECK(uart_driver_install(uart_motor_control, uart_buffer_size, uart_buffer_size, 0, NULL, 0));
212 ESP_ERROR_CHECK(uart_driver_install(uart_blade_control, uart_buffer_size, uart_buffer_size, 0, NULL, 0));
213 ESP_ERROR_CHECK(uart_set_mode(uart_motor_control, UART_MODE_UART));
214 ESP_ERROR_CHECK(uart_set_mode(uart_blade_control, UART_MODE_UART));
215
216 printf("registering shutdown function\n");
217 esp_register_shutdown_handler(onrestart);
218
219 printf("creating ping task\n");
220 TaskHandle_t pingTaskHandle = NULL;
221 xTaskCreate(pingTask, "pingTask", 2000, (void *)true, tskIDLE_PRIORITY, &pingTaskHandle);
222
223 printf("creating radio task\n");
224 TaskHandle_t radioTaskHandle = NULL;
225 xTaskCreate(radioTask, "radioTask", 10000, (void *)true, 1, &radioTaskHandle);
226
227 printf("pulling STATUS_[YELLOW|RED] LOW\n");
228 gpio_set_level(STATUS_YELLOW, LOW);
229 gpio_set_level(STATUS_RED, LOW);
230}
231