rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
can_sensor.h
Go to the documentation of this file.
1/**
2 * @file can_sensor.h
3 *
4 * @date March 31, 2020
5 * @author Matthew Kennedy, (c) 2020
6 */
7
8#pragma once
9
10#include "stored_value_sensor.h"
11#include "efi_scaled_channel.h"
12#include "can_msg_tx.h"
13#include "obd2.h"
14#include "can.h"
15#include "can_listener.h"
16
17/**
18 * Sensor which reads it's value from CAN
19 */
21public:
22 CanSensorBase(uint32_t eid, SensorType type, efidur_t timeout)
23 : StoredValueSensor(type, timeout)
24 , CanListener(eid)
25 {
26 }
27
28 void showInfo(const char* sensorName) const override;
29};
30
31template <typename TStorage, int TScale>
32class CanSensor : public CanSensorBase {
33public:
34 CanSensor(uint32_t eid, uint8_t offset, SensorType type, efidur_t timeout)
35 : CanSensorBase(eid, type, timeout)
37 {
38 }
39
40 void decodeFrame(const CANRxFrame& frame, efitick_t nowNt) override {
41 // Compute the location of our data within the frame
42 const uint8_t* dataLocation = &frame.data8[m_offset];
43
44 // Reinterpret as a scaled_channel - it already has the logic for decoding a scaled integer to a float
45 const auto scaler = reinterpret_cast<const scaled_channel<TStorage, TScale>*>(dataLocation);
46
47 // Actually do the conversion
48 float value = *scaler;
49 setValidValue(value, nowNt);
50 }
51
52private:
53 const uint8_t m_offset;
54};
55
56#if EFI_PROD_CODE
57
58template <int Size, int Offset>
60public:
61 ObdCanSensor(int p_PID, float p_Scale, SensorType type) :
62 CanSensorBase(OBD_TEST_RESPONSE, type, /* timeout, never expire */ 0) {
63 this->PID = p_PID;
64 this->Scale = p_Scale;
65 }
66
67 void decodeFrame(const CANRxFrame& frame, efitick_t nowNt) override {
68 if (frame.data8[2] != PID) {
69 return;
70 }
71
72 int iValue;
73 if (Size == 2) {
74 iValue = frame.data8[3] * 256 + frame.data8[4];
75 } else {
76 iValue = frame.data8[3];
77 }
78
79 float fValue = (1.0 * iValue / Scale) - Offset;
80 setValidValue(fValue, nowNt);
81 }
82
83 CanListener* request() override {
84 {
85 CanTxMessage msg(CanCategory::OBD, OBD_TEST_REQUEST);
86 msg[0] = _OBD_2;
87 msg[1] = OBD_CURRENT_DATA;
88 msg[2] = PID;
89 }
90 // let's sleep on write update after each OBD request, this would give read thread a chance to read response
91 // todo: smarter logic of all this with with semaphore not just sleep
92 chThdSleepMilliseconds(300);
93 return CanListener::request();
94 }
95
96 int PID;
97 float Scale;
98};
99
100#endif // EFI_PROD_CODE
virtual CanListener * request()
void showInfo(const char *sensorName) const override
CanSensorBase(uint32_t eid, SensorType type, efidur_t timeout)
Definition can_sensor.h:22
const uint8_t m_offset
Definition can_sensor.h:53
void decodeFrame(const CANRxFrame &frame, efitick_t nowNt) override
Definition can_sensor.h:40
CanSensor(uint32_t eid, uint8_t offset, SensorType type, efidur_t timeout)
Definition can_sensor.h:34
CanListener * request() override
Definition can_sensor.h:83
ObdCanSensor(int p_PID, float p_Scale, SensorType type)
Definition can_sensor.h:61
void decodeFrame(const CANRxFrame &frame, efitick_t nowNt) override
Definition can_sensor.h:67
SensorType type() const
Definition sensor.h:162
Base class for sensors that compute a value on one thread, and want to make it available to consumers...
void setValidValue(float value, efitick_t timestamp)
efitick_t efidur_t
SensorType
Definition sensor_type.h:18
Base class for a sensor that has its value asynchronously set, then later retrieved by a consumer.
uint8_t data8[8]
Frame data.
Definition can_mocks.h:55
uint16_t offset
Definition tunerstudio.h:0