forked from janpom/davega
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathroxie-firmware.ino
206 lines (173 loc) · 6.32 KB
/
roxie-firmware.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
This file is part of the Roxie firmware.
Roxie firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Roxie firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Roxie firmware. If not, see <https://www.gnu.org/licenses/>.
*/
#include "roxie_config.h"
#include "eeprom_backup.h"
#include "util.h"
#include "screen.h"
#include "vesc_comm.h"
#include "button_interrupt.h"
#include "vertical_screen.h"
#include "vertical_screen2.h"
//#include "screen_data.h"
//#include "ssd1306_screen.h"
#ifdef FOCBOX_UNITY
#include "vesc_comm_unity.h"
VescCommUnity vesc_comm = VescCommUnity();
#else
#include "vesc_comm_standard.h"
VescCommStandard vesc_comm = VescCommStandard();
#endif
VerticalScreen vertical_screen;
VerticalScreen2 vertical_screen2;
t_screen_config screen_config;
t_data data; // struct containing data received from vesc
t_session_data session_data; // data from this session
int32_t startup_trip_meters; // trip meters that were stored in the EEPROM on startup
int32_t startup_total_meters; // total meters that were stored in the EEPROM on startup
int32_t last_total_meters_stored;
int32_t last_stopped;
int32_t last_rpm;
Button button1 = Button(BUTTON_1_PIN);
Button button2 = Button(BUTTON_2_PIN);
Button button3 = Button(BUTTON_3_PIN);
//ScreenData test;
//HardwareSerial Serial3(PB11, PB10);
void setup()
{
// Initialize communication with computer for debugging and with vesc
#ifdef ARDUINO_NANO_EVERY
Serial.begin(115200);
#endif
vesc_comm.init(115200);
attachInterrupt(digitalPinToInterrupt(BUTTON_1_PIN), button1_changed, CHANGE);
attachInterrupt(digitalPinToInterrupt(BUTTON_2_PIN), button2_changed, CHANGE);
attachInterrupt(digitalPinToInterrupt(BUTTON_3_PIN), button3_changed, CHANGE);
screen_config = {make_fw_version(FW_VERSION, REVISION_ID), IMPERIAL_UNITS, USE_FAHRENHEIT,
SHOW_AVG_CELL_VOLTAGE, BATTERY_S, SCREEN_ORIENTATION};
vertical_screen = VerticalScreen();
vertical_screen2 = VerticalScreen2();
// Initialize EEPROM and/or read stored data from it.
if (!eeprom_is_initialized(EEPROM_MAGIC_VALUE))
{
eeprom_initialize(EEPROM_MAGIC_VALUE, session_data, data);
}
eeprom_read_data(&data, session_data);
// Initialize the screen and draw the basic interface
vertical_screen.init(&screen_config);
vertical_screen.draw_basic();
vesc_comm.fetch_packet();
while (!vesc_comm.is_expected_packet())
{
vertical_screen.heartbeat(UPDATE_DELAY, false);
vesc_comm.fetch_packet();
}
vesc_comm.process_packet(&data);
load_startup_values();
vertical_screen.update(&data);
}
bool default_screen = true;
void loop()
{
check_buttons();
vesc_comm.fetch_packet();
if (!vesc_comm.is_expected_packet())
{
vertical_screen.heartbeat(UPDATE_DELAY, false);
return;
}
vesc_comm.process_packet(&data);
process_other_values();
if(default_screen){
vertical_screen.update(&data);
vertical_screen.heartbeat(UPDATE_DELAY, true);
} else {
vertical_screen2.update(&data);
vertical_screen2.heartbeat(UPDATE_DELAY, true);
}
}
void check_buttons()
{
button1.update_button();
button2.update_button();
button3.update_button();
if(button1.get_clicked() || button2.get_clicked())
{
DEB("button 1 or 2 pushed");
if (default_screen)
{
vertical_screen2.init(&screen_config);
vertical_screen2.draw_basic();
default_screen = false;
} else {
vertical_screen.init(&screen_config);
vertical_screen.draw_basic();
default_screen = true;
}
}
if(button3.get_long_click())
{
DEB("button 3 pushed");
startup_trip_meters = 0 - rotations_to_meters(data.tachometer / 6);
vertical_screen.process_buttons(&data, true);
}
}
void load_startup_values()
{
// Store the trip and total meter values on startup
t_session_data startup = eeprom_read_session_data();
startup_trip_meters = startup.trip_meters;
startup_total_meters = eeprom_read_total_distance(); // TODO: read from data instead of EEPROM
last_total_meters_stored = startup_total_meters; // set the startup values as the last values stored in EEPROM
// Subtract current VESC values, which could be non-zero in case the display
// got reset without resetting the VESC as well. The invariant is:
// current value = initial value + VESC value
// and that works correctly with the default initial values in case the VESC values
// start from 0. If that's not the case though we need to lower the initial values.
int32_t tachometer = rotations_to_meters(data.tachometer / 6);
startup_trip_meters -= tachometer;
startup_total_meters -= tachometer;
}
void process_other_values()
{
int32_t tachometer_meters = rotations_to_meters(data.tachometer / 6);
session_data.trip_meters = startup_trip_meters + tachometer_meters;
int32_t total_meters = startup_total_meters + tachometer_meters;
data.trip_km = session_data.trip_meters / 1000.0;
data.total_km = total_meters / 1000.0;
// update EEPROM
bool came_to_stop = (last_rpm != 0 && data.rpm == 0);
bool traveled_enough_distance = (total_meters - last_total_meters_stored >= EEPROM_UPDATE_EACH_METERS);
if (traveled_enough_distance || (came_to_stop && millis() - last_stopped > EEPROM_UPDATE_MIN_DELAY_ON_STOP))
{
if (came_to_stop)
last_stopped = millis();
last_total_meters_stored = total_meters;
eeprom_write_total_distance(total_meters);
eeprom_write_session_data(session_data);
}
last_rpm = data.rpm;
}
//ISR routines for the buttons
void button1_changed()
{
button1.button_changed();
}
void button2_changed()
{
button2.button_changed();
}
void button3_changed()
{
button3.button_changed();
}