Hi, and thanks for looking I'm using an Arduino Nano 33 IoT to read rotation on a bicycle pedal bar, it then sends the data over UDP, but if I really give it a whirl, at high speeds the rotation output seems to be stuck until I slow down again. I have a delay of 10 seconds each loop since the accelerometer works at 104Hz anyway, but I've tried removing the delay, but that didn't seem to make a difference. I've changed the batteries, but I only had rechargeables that can't power it because they're only 1.2V at full charge instead of regular AA at 1.5V.
Question 1: Can the rotation be too fast for the accelerometer?
Question 2: Can low battery charge be an issue here?
Question 3: A bit far-fetched, but could it be the Wifi that doesn't work correctly at high speeds?
Any other info related to this will be greatly appreciated
It can but I doubt you reach it (If I calculated right, the rotation must be clearly about 300rpm to get near the max. acceleration the sensor can measure and I doubt the sensor will get stuck if you reach that.
Probably not otherwise the problem would be consistent at lower speeds.
WiFi isn't that speed tolerant but usually that speed is outside of what humans reach. What range of accelerations are we talking about?
My code was wrong, but I still haven't achieved what I am looking for.
I have removed the delay in the main loop.
I want to check for an entire revolution which is then added to a revolution counter. I have made a check to see if the latest angle read is higher than the previous read (because the angle can jump +/- a few degrees), if so I use the new angle.
If the newly read angle is less than the old - 180, a complete revolution must have been made.
I have set the hex value to 69 for the LSM6DS3 CTRL1_XL register (LSM6DS3 Datasheet page 54) in the source for that library so that the configuration should be 4G updating at 416Hz and filter to 200Hz. I am still having a hard time accurately measuring complete revolutions.
Could really do with seeing the code - it maybe at high speed the crank makes several revs before your sketch reads it or you have an over flow problem
Hi Hammy, here's the code, it does seem to work much better now, both at low and high speed. The angle doesn't update much at high speeds but that's fine because there I can use the RPM updates instead. The angle is just fine at low speed where I use the angle in conjunction with the RPMs. Any inputs will be greatly appreciated
#include <SPI.h>
#include <WiFiNINA.h>
#include <Arduino_LSM6DS3.h> //Arduino_LSM6DS3.cpp has a modified register, writeRegister(LSM6DS3_CTRL1_XL, 0x69) so that the accelerometer updates at 416hz, scaled to 4G with a 200Hz filter
#define PI 3.1415926535897932384626433832795
float x, y, z;
int rotationInDegrees;
int oldRotationsInDegrees;
bool sendBuffers = false;
int totalRevolutions = 0;
bool bits[16];
bool readyForNewRevolution = true;
char ssid[] = "********"; // Wifi SSID
char pass[] = "********"; // Wifi password
WiFiUDP Udp;
int localPort = 5000;
int status = WL_IDLE_STATUS;
// Initialize the Wifi client
WiFiSSLClient client;
char UDPDegreesBuffer[2];
byte UDPRevolutionsBuffer[2];
void setup()
{
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE)
{
//Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
connectToAP(); // Connect to Wifi Access Point
}
void loop()
{
if (IMU.accelerationAvailable())
{
IMU.readAcceleration(x, y, z);
}
x = 100 * x;
z = 100 * z;
rotationInDegrees = ((atan2(x, z) * 180) / PI) + 180;
if (rotationInDegrees > oldRotationsInDegrees)
{
oldRotationsInDegrees = rotationInDegrees;
sendBuffers = true;
}
if (rotationInDegrees > 180 && rotationInDegrees < 270)
{
readyForNewRevolution = true; //To prevent revolution counter to be bopping around 360 and 0
sendBuffers = true;
}
if (rotationInDegrees > 0 && rotationInDegrees < 90 && readyForNewRevolution)
{
++totalRevolutions;
SetBits(totalRevolutions);
BuildRevolutionsBuffer();
oldRotationsInDegrees = rotationInDegrees;
sendBuffers = true;
readyForNewRevolution = false;
}
if (rotationInDegrees > 255)
{
UDPDegreesBuffer[0] = 255;
UDPDegreesBuffer[1] = rotationInDegrees - 255;
}
else
{
UDPDegreesBuffer[0] = rotationInDegrees;
UDPDegreesBuffer[1] = 0;
}
if (sendBuffers == true)
{
sendBuffers = false;
// Send data over UDP
Udp.beginPacket("192.168.0.88", 5001);
Udp.write(UDPDegreesBuffer, 2);
Udp.write(UDPRevolutionsBuffer, 2);
Udp.endPacket();
}
}
void SetBits(int value)
{
int nominator = 32768;
for (int t = 0; t < 16; ++t)
{
bits[t] = 0;
if (value >= nominator)
{
value = value - nominator;
bits[t] = 1;
}
nominator = ceil(nominator / 2);
}
}
void BuildRevolutionsBuffer()
{
for (int i = 0; i < 2; ++i)
{
int nominator = 128;
int value = 0;
for (int t = (0 + (i * 8)); t < (8 + (i * 8)); ++t)
{
if (bits[t] == 1)
{
value = value + nominator;
}
nominator = ceil(nominator / 2);
}
UDPRevolutionsBuffer[i] = value;
}
}
void connectToAP() {
// Try to connect to Wifi network
while ( status != WL_CONNECTED) {
//Serial.print("Attempting to connect to SSID: ");
//Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
// wait 1 second for connection:
delay(1000);
//Serial.println("Connected...");
Udp.begin(localPort);
IMU.begin();
}
}