I want to make a counter because distance data goes to zero when it reach 30000(600 meters).
Meters are printed fine, when car move, meters are running, when car stops meters stop running.
But counter increase it's value endlessly, if meters are two, then counter is 4, 8, 16 etc. until i turn ignition off.
I tried other ways instead of counter += meters, but always same result.
So, i want counter simply store meters, not multiply it all the time.
#include <mcp_can.h>
#include <SPI.h>
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128]; // Array to store serial string
#define CAN0_INT 2 // Set INT to pin 2
MCP_CAN CAN0(9); // Set CS to pin 9
uint32_t meters;
uint32_t counter;
void setup() {
Serial.begin(115200);
// Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
CAN0.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data.
pinMode(CAN0_INT, INPUT); // Configuring pin for /INT input
}
void loop() {
if(!digitalRead(CAN0_INT)) // If CAN0_INT pin is low, read receive buffer
{
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)
sprintf(msgString, "Standard ID: 0x%.3lX DLC: %1d Data:", rxId, len);
for (byte i = 0; i < len; i++) {
sprintf(msgString, " 0x%.2X", rxBuf[i]);
// Serial.print(msgString);
}
}
if (rxId == 0x5A0) {
uint16_t rawDistance = (uint16_t)rxBuf[6] << 8;
rawDistance |= rxBuf[5];
meters = uint32_t (rawDistance / 50);
counter += meters;
Serial.println(meters);
Serial.println(counter);
}
}
It will change when other can-frames are received.
I had there else if for other can-frames, but i deleted for this example.
In my understanding that should not play a role with this.
Maybe i did not understand what you mean.
That sounds like a problem if it is true because if the message with an rxId of 0x5A0 is received repeatedly then no wonder that the counter variable is updated frequently
In this 0x540, byte 5 is low byte and 6 is high for distance.
I wonder why meters are counted as it should still.
In my opinion, meters should be divided with 50 also every time. Fortunately no in this case.
81 meters is a 'distanceTraveled' of 4050.
1351 meters is a 'distanceTraveled' of 67500;
the difference is 63450. That is close to 65535, the maximum value that fits in an uint16_t. I suspect a math underflow where rawDistance was less than lastRawDistance. That would result in a small negative number which looks like a very large unsigned number.
Try this version which will report any backward counting:
if (rxId == 0x5A0)
{
static uint16_t lastRawDistance = 0;
uint16_t rawDistance = (uint16_t)rxBuf[6] << 8;
rawDistance |= rxBuf[5];
uint16_t newRawDistance = rawDistance - lastRawDistance;
// Report a problem if the distance traveled is more
// than a kilometer.
if (newRawDistance > 50000u)
{
Serial.println("Math problem");
Serial.print(" lastRawDistance: ");
Serial.println(lastRawDistance);
Serial.print(" rawDistance: ");
Serial.println(rawDistance);
while(1) {} // Halt the sketch if this error occurs.
}
distanceTraveled += newRawDistance;
lastRawDistance = rawDistance;
meters = distanceTraveled / 50;
// Only report the distance traveled when meters change
// to avoid spamming the serial output
static uint32_t lastMeters = 0;
if (meters != lastMeters)
{
Serial.println(meters);
lastMeters = meters;
}
}
Problem report come almost immediately when car moves. Cannot get more than 2 meters, that is the record. Once report came even a car did not move at all.
Yes when rawDistance is less than lastRawdistance.
That is weird. 136 isn't less than 136 and 62 isn't less than 62. After the subtractions, the newRawDistance should be zero, not > 50000!
Of course, 223 IS less than 224 so subtracting 224 from 223 gives an underflow: 65535. That shows that the 'rawDistance' can go DOWN. Let's try ignoring backward motion:
if (rxId == 0x5A0)
{
static uint16_t lastRawDistance = 0;
uint16_t rawDistance = (uint16_t)rxBuf[6] << 8;
rawDistance |= rxBuf[5];
uint16_t newRawDistance = rawDistance - lastRawDistance;
// Report a problem if the distance traveled is more
// than a kilometer.
if (newRawDistance > 50000u)
{
Serial.println("Moving backward? Ignoring.");
Serial.print(" lastRawDistance: ");
Serial.println(lastRawDistance);
Serial.print(" rawDistance: ");
Serial.println(rawDistance);
newRawDistance = 0;
}
distanceTraveled += newRawDistance;
lastRawDistance = rawDistance;
meters = distanceTraveled / 50;
// Only report the distance traveled when meters change
// to avoid spamming the serial output
static uint32_t lastMeters = 0;
if (meters != lastMeters)
{
Serial.println(meters);
lastMeters = meters;
}
}
I do not understand why it think newRawDistance is over 50000, but it meters come as should in this short test.
Because rawDistance - lastRawDistance as mentioned?