blob: c42e609f7e778e37e21541885b39039b9b0eb9a6 [file] [log] [blame]
Daniel Pettiaece37f2014-10-25 17:13:44 -07001#include <inttypes.h>
2
3#include "aos/linux_code/init.h"
4#include "aos/common/logging/logging.h"
5#include "aos/common/util/wrapping_counter.h"
6#include "aos/common/time.h"
7#include "aos/common/logging/queue_logging.h"
8#include "aos/common/controls/output_check.q.h"
9
10#include "bbb/sensor_reader.h"
11
12#include "bot3/control_loops/drivetrain/drivetrain.q.h"
13#include "bot3/control_loops/drivetrain/drivetrain_constants.h"
14#include "bot3/queues/to_log.q.h"
Daniel Petti532c3e92014-11-04 22:15:19 -080015#include "bot3/shifter_hall_effect.h"
Daniel Pettiaece37f2014-10-25 17:13:44 -070016#include "frc971/queues/other_sensors.q.h"
Daniel Pettiaece37f2014-10-25 17:13:44 -070017
18#ifndef M_PI
19#define M_PI 3.14159265358979323846
20#endif
21
22using ::bot3::control_loops::drivetrain;
23using ::frc971::sensors::gyro_reading;
24using ::aos::util::WrappingCounter;
25
26namespace bot3 {
27namespace {
28
29// TODO (danielp): Find out the real ratios here.
30double drivetrain_translate(int32_t in) {
31 return static_cast<double>(in)
32 / (256.0 /*cpr*/ * 4.0 /*quad*/)
33 * (18.0 / 50.0 /*output stage*/) * (56.0 / 30.0 /*encoder gears*/)
34 // * constants::GetValues().drivetrain_encoder_ratio
35 * (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI);
36}
37
38static const double kVcc = 5.15;
39
40// Translates values from the ADC into voltage.
41double adc_translate(uint16_t in) {
42 if (false) {
43 // This is the simple theoretical math.
44 static const uint16_t kMaximumValue = 0x3FF;
45 static const double kR1 = 5, kR2 = 6.65;
46 const double raw =
47 (kVcc * static_cast<double>(in) / static_cast<double>(kMaximumValue));
48 return (raw * (kR1 + kR2) - (kVcc / 2) * kR2) / kR1;
49 } else {
50 // This is from a linear regression calculated with some actual data points.
51 static const double kM = 0.012133, kB = -3.6813;
52 return static_cast<double>(in) * kM + kB;
53 }
54}
55
56double battery_translate(uint16_t in_high, uint16_t in_low) {
57 const double high = adc_translate(in_high), low = adc_translate(in_low);
58 static const double kDividerBig = 5.55, kDividerSmall = 2.66;
59 return (high - low) * (kDividerBig + kDividerSmall) / kDividerSmall +
60 kDividerBig / kDividerSmall * kVcc;
61}
62
63double gyro_translate(int64_t in) {
64 return in / 16.0 / 1000.0 / (180.0 / M_PI);
65}
66
Daniel Petti532c3e92014-11-04 22:15:19 -080067double hall_translate(const constants::ShifterHallEffect & k,
68 uint16_t in_value) {
69 return (in_value - static_cast<double>(k.low)) /
70 static_cast<double>(k.high - k.low);
Daniel Pettiaece37f2014-10-25 17:13:44 -070071}
72
73void PacketReceived(const ::bbb::DataStruct *data,
74 const ::aos::time::Time &cape_timestamp) {
75 ::aos::time::TimeFreezer time_freezer;
76
77 ::frc971::logging_structs::CapeReading reading_to_log(
78 cape_timestamp, static_cast<uint16_t>(sizeof(*data)),
79 data->main.low_left_drive_hall, data->main.high_left_drive_hall,
80 data->main.low_right_drive_hall, data->main.high_right_drive_hall);
81 LOG_STRUCT(DEBUG, "cape reading", reading_to_log);
82 bool bad_gyro;
83 // TODO(brians): Switch to LogInterval for these things.
84 if (data->uninitialized_gyro) {
85 LOG(DEBUG, "uninitialized gyro\n");
86 bad_gyro = true;
87 } else if (data->zeroing_gyro) {
88 LOG(DEBUG, "zeroing gyro\n");
89 bad_gyro = true;
90 } else if (data->bad_gyro) {
91 LOG(ERROR, "bad gyro\n");
92 bad_gyro = true;
93 } else if (data->old_gyro_reading) {
94 LOG(WARNING, "old/bad gyro reading\n");
95 bad_gyro = true;
96 } else {
97 bad_gyro = false;
98 }
99
100 if (!bad_gyro) {
101 gyro_reading.MakeWithBuilder()
102 .angle(gyro_translate(data->gyro_angle))
103 .Send();
104 }
105
106 if (data->analog_errors != 0) {
107 LOG(WARNING, "%" PRIu8 " analog errors\n", data->analog_errors);
108 }
109
110 if (data->main.output_check_pulse_length != 0) {
111 auto message = ::aos::controls::output_check_received.MakeMessage();
112 // TODO(brians): Fix this math to match what the cRIO actually does.
113 // It's close but not quite right.
114 message->pulse_length =
115 static_cast<double>(data->main.output_check_pulse_length) / 10000.0;
116 if (message->pulse_length > 2.7) {
117 LOG(WARNING, "insane PWM pulse length %fms\n", message->pulse_length);
118 } else {
119 message->pwm_value = (message->pulse_length - 0.5) / 2.0 * 255.0 + 0.5;
120 LOG_STRUCT(DEBUG, "received", *message);
121 message.Send();
122 }
123 }
124
125 drivetrain.position.MakeWithBuilder()
126 .right_encoder(drivetrain_translate(data->main.right_drive))
127 .left_encoder(-drivetrain_translate(data->main.left_drive))
128 .left_shifter_position(hall_translate(control_loops::kBot3LeftDriveShifter,
Daniel Petti532c3e92014-11-04 22:15:19 -0800129 data->main.low_left_drive_hall))
Daniel Pettiaece37f2014-10-25 17:13:44 -0700130 .right_shifter_position(hall_translate(control_loops::kBot3RightDriveShifter,
Daniel Petti532c3e92014-11-04 22:15:19 -0800131 data->main.low_right_drive_hall))
Daniel Pettiaece37f2014-10-25 17:13:44 -0700132 .battery_voltage(battery_translate(data->main.battery_voltage_high,
133 data->main.battery_voltage_low))
134 .Send();
135}
136
137} // namespace
138} // namespace bot3
139
140int main() {
141 ::aos::Init(::bbb::SensorReader::kRelativePriority);
142 ::bbb::SensorReader reader("comp");
143 while (true) {
144 ::bot3::PacketReceived(reader.ReadPacket(), reader.GetCapeTimestamp());
145 }
146 ::aos::Cleanup();
147}