PragmaticPhilKalbeAbbas
Published © GPL3+

Measure Speed of Rotation of a Wheel with XinaBox & Magnets

Build an instrument to measure the RPM / speed of a spinning wheel using the XinaBox magnetometer (SI01).

IntermediateFull instructions provided1 hour798
Measure Speed of Rotation of a Wheel with XinaBox & Magnets

Things used in this project

Hardware components

CW01
XinaBox CW01
Wi-Fi Core (ESP8266/ESP-12F)
×1
SI01
XinaBox SI01
Magnetometer, accelerometer and gysoscope
×1
OD01
XinaBox OD01
OLED Display 128x64 (SSD1306)
×1
IP01
XinaBox IP01
An interface module equipped to power and program other modules via a USB A connector
×1
XC10
XinaBox XC10
These standard uBus connectors are used to fit XinaBox xChips together. This SKU is a pack of 10. Alternately search "Male PCB Edge Connector SMT, 10 Way, 2 Row, 2mm Pitch" for generics. You need 4 for this project.
×1

Software apps and online services

Arduino IDE
Arduino IDE
In this project we use ArduinoIDE to flash code onto the XinaBox CW01 core.

Story

Read more

Schematics

Building the XinaBox RPM circuit

The file is just an image of the circuit - the same image used in the story. If you have all the required hardware listed then the image is ALL you will need to put the circuit together: it should take you less than a minute to build it and even less to take it apart. No soldering, bread-boarding or wires are required and you don't need any hardware knowledge to build it

Code

Code for RPM counter

C/C++
Code written by Kalbe Abbas :)
#include <xCore.h>
#include <xSI01.h>
#include <xOD01.h>

xSI01 SI01;
xOD01 OD01;

int count = 0; //Count rotations
int prevCount = 0; //Previous count
boolean en = false; //Conditional variable
float xMax, yMax, zMax; //Calibration variables
float MX,MY,MZ;
float absMX, absMY, absMZ;
float closeMagneticValue; //Threshold Magnetic field
static unsigned long tick; //timer variable


//Print speeds to updated OD01
#define PRINT_SPEED 500
#define PRINT_SPEED2 1000

static unsigned long lastPrint, lastPrint2 = 0; //last print time
static unsigned long update_time = 0; //Time when count increases in millis()
static unsigned long prev_time = 0; //Previous count time in millis()
static unsigned long rpm_time = 0; //Difference in time between two counts

static float rpm = 0.0; //Revolution per minute

void setup() {
  // Start the Serial Monitor at 115200 BAUD

  xMax = yMax = zMax = 0;
  closeMagneticValue = 0;

  Serial.begin(115200);

  // Set the I2C Pins for CW01
#ifdef ESP8266
  Wire.pins(2, 14);
  Wire.setClockStretchLimit(15000);
#endif

  Wire.begin();

  SI01.begin();
  OD01.begin();
  /*if (!SI01.begin()) {
    Serial.println("Failed to communicate with SI01.");
    Serial.println("Check the Connector");
    } else {
    Serial.println("start successful");
    }*/
  OD01.set2X();

  OD01.println("RPM Counter");

  tick = millis();

  Serial.println("Calibration");

  OD01.println("Calibration");

  delay(2000);

  //Calibration, threshold value
  while ((millis() - tick) < 5000)
  {

    SI01.poll();
    MX=SI01.getMX();
    MY=SI01.getMY();
    MZ=SI01.getMZ();
    absMX = abs(MX);
    absMY = abs(MY);
    absMZ = abs(MZ);
    xMax = max(absMX, xMax);
    yMax = max(absMY, yMax);
    zMax = max(absMZ, zMax);
    Serial.print(".");
    delay(10);
  }

  OD01.clear();

  OD01.println("Done!");

  delay(2000);

  OD01.clear();
  closeMagneticValue = max(xMax, yMax);
  closeMagneticValue = max(zMax, closeMagneticValue);
  
  //  The following line sets the threshold at which en switches
  //  when the magenetometer reading is greater than 0.6 * closeMagneticValue
  //  we set en to True, meaning the magnet is close to the magnetometer
  //  we then set it to False when the value is below this threhold and
  //  we count a rotation when it changes from true to false
  closeMagneticValue *= 0.6;
  //  You could tweak the constant above - lower values may help you to 
  //  increase the maximum revolutions per second that this code can support!

  Serial.println();
  Serial.print("Close Magnetic Value: ");
  Serial.println(closeMagneticValue);

  //OD01.clear();
}

void loop() {
  // Read and calculate data from SI01 sensor
  SI01.poll();

  //Enable condition variable en when Magnet enter range of SI01
  if (abs(SI01.getMX()) >= closeMagneticValue || abs(SI01.getMY()) >= closeMagneticValue || abs(SI01.getMZ()) >= closeMagneticValue)
  {
    en = true;
  }

  //Increae count when Magnet leaves SI01 range
  if ((abs(SI01.getMX()) < closeMagneticValue) && (abs(SI01.getMY()) < closeMagneticValue) && (abs(SI01.getMZ()) < closeMagneticValue) && (en == true)) {
    count++;
    update_time = millis();
    en = false;
  }

  //Calculate RPM
  if ((count != prevCount) && (count%10==0)) {
    rpm_time = update_time - prev_time;
    prev_time = update_time;
    if ((rpm_time != 0)) {
      rpm = ((60000.0 *10.0) / rpm_time);
    }
  }

  if ((lastPrint + PRINT_SPEED) < millis()) {
    Serial.print("RPM: ");
    Serial.println(rpm);
    Serial.print("Count: ");
    Serial.println(count);

    OD01.print("RPM: ");
    OD01.println(rpm);
    OD01.print("Count: ");
    OD01.println(count);

    lastPrint = millis();
  }
  if ((lastPrint2 + PRINT_SPEED2) < millis()) {
    OD01.clear();
    lastPrint2 = millis();
  }

}

Credits

PragmaticPhil
17 projects • 17 followers
Pragmatic hobbyist
Contact
KalbeAbbas
25 projects • 20 followers
An enthusiastic and dedicated Electronic engineer graduated from SSUET Karachi, Pakistan. Loves to discover Embedded electronics projects.
Contact

Comments

Please log in or sign up to comment.