Transmitting data from GPS to SIGFOX - c++

I'm working on an Arduino board (microprocessor: ATMega328P) for a University project. I'd like to build a GPS tracker which receives data, stores it, and retransmit it via SIGFOX module.
Basically, I'm able to receive data, and I'm able to send simple SIGFOX commands via serial.
#include <TinyGPS++.h>
#include <String.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);
Serial.println(F("DeviceExample.ino"));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println();
}
void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read())) {
Serial.print(gps.location.lat(), 6); // 4 bytes
Serial.print(F(",")); // 1 byte
Serial.print(gps.location.lng(), 6); // 4 bytes
Serial.print('\n');
delay(4000);
}
if (millis() > 5000 && gps.charsProcessed() < 10){
Serial.println(F("No GPS detected: check wiring."));
while (true);
}
}
This prints correctly on screen the two values (latitude and longitude) that I need to store.
This is the part of the code in TinyGPS++.cpp :
double TinyGPSLocation::lat()
{
updated = false;
double ret = rawLatData.deg + rawLatData.billionths / 1000000000.0;
return rawLatData.negative ? -ret : ret;
}
double TinyGPSLocation::lng()
{
updated = false;
double ret = rawLngData.deg + rawLngData.billionths / 1000000000.0;
return rawLngData.negative ? -ret : ret;
}
Now I'd like to store this data and send it through the SIGFOX module.
A SIGFOX command is:
'N X'
Where N represents the number of bytes that are to be transmitted, and X are the values of the bytes. For example: '1 255' is 1 byte with value 255, and returns FF as output.
The problem is that the values are doubles so I don't know how to write them in the SIGFOX command.
Another problem is that I don't know how to create two serial communications in the code. I tried it but it doesn't seem to work.
Thank you so much in advance.

I saw some of the API info on the SIGFOX, I'm assuming it is this. Even if it isn't it's probably close enough for the point I'm trying to make.
https://support.sigfox.com/apidocs#operation/getDevice
You need to understand to some extent what IEEE 754 is as in my experience this is how equipment passes the data back and forth if you look at the raw bit stream.
https://en.wikipedia.org/wiki/IEEE_754
So, it is a double you send over 8 bytes on most platforms and 4 bytes for a float. When you print to the screen of hover over a variable in debug mode, the IDE/compiler takes care of this for you and gives you number with decimal points.
For making another serial port, you need to make another variable and pass in the baud rate etc of that device.

Related

communicating state of a potentiometer with a second arduino board

I am trying to get an arduino board to read the state of a potentiometer which is connected to a master arduino board, without connecting the potentiometer to the second board with physical cables
I have tried using Wire.write and Wire.read to just transfer the one value.
The master arduino code:
#include <Wire.h>
const int dial = A0;
int reading = 0;
void setup() {
pinMode(dial, INPUT);
Wire.begin();
}
void loop() {
reading = analogRead(dial);
Wire.beginTransmission(9);
Wire.write(reading);
Wire.endTransmission();
}
The slave arduino code:
#include <Wire.h>
int reading = 0;
void setup() {
Wire.begin(9);
Serial.begin(9600);
Wire.onReceive(receiveEvent);
}
void receiveEvent(int bytes) {
reading = Wire.read();
}
void loop() {
Serial.println(reading);
}
When I read the Serial Monitor, the potentiometer or "reading" in the slave arduino limits at 255 (I don't know why) in 6 intervals (goes from 0 to 255, then drops to 0 and does that 6 times). I expect it to do the full range of the potentiometer to cap out at 1023.
Your ADC is 10bit and won’t fit in a byte. (Wire.write(value) sends value as a single byte). You need to send reading in 2 bytes. Here is how to make 2 bytes.
byte data1 = highByte(reading);
byte data2 = lowByte(reading);
On receiving side, reconstruct an int this way.
byte data1 = Wire.read();
byte data2 = Wire.read();
reading = int(data1) << 8 | data2;

recieving Frame of 8 bytes in QT Creator GUI via serial port

I'm working to send frame of 8 bytes to Micro-controller Xmega128a1 (via RS232) the frame looks like this
{header1,header2,CMD,D1,D2,D3,D4,CRC},
for example
{0x55,0xaa,0xFF,0x59,0xfd,0x64,0x68,0x32},
Micro-controller has to resend the frame back to PC, if it's 'correct'.
I built GUI in QT Creator I defined the Headers (header0=0x55, header1=0xaa) and CMD=01 also calculated the CRC,
the user has to enter the data field in the Line_Edit which is value in RPM(Real value) The Micro-controller Receive the frame byte byte and resend the full frame, so I have to send the frame in the form of bytes, when I send the frame I receive the headers, command and CRC correctly, but data field Received not in proper way such in the picture below, my problem is with converting the input value in the Line_Edit to bytes to be send inside the frame, when I tried to send the value 1265 RPM I received the frame {55aa0100209e44fb} but I want to receive the frame look like this {55aa014F109e44fb}, where: (1265)DC=(4F1)HEX, I couldn't figure what's the problem with my code:
the way I read data from serial port:
void MainWindow::read()
{
uint64_t size = serial->bytesAvailable();
if (size > 0)
{
QByteArray data;
data.append(serial->readAll());
ui->termial_textEdit->append(data.toHex());
}
}
the send value in RPM code:
#define CMD_SPEED_REF2 0x01
void MainWindow::on_speed_ref2_lineEdit_returnPressed()
{
uint8_t frame2[8];
frame2[0] = 0x55;
frame2[1] = 0xAA;
frame2[2] = CMD_SPEED_REF2;
float fdata2 = 0.0f;
fdata2 = ui->speed_ref2_lineEdit->text().toFloat();
uint8_t *data2 = new uint8_t();
data2 = (uint8_t*)&fdata2;
frame2[3] = data2[0];
frame2[4] = data2[1];
frame2[5] = data2[2];
frame2[6] = data2[3];
frame2[7] = frame2[2] ^ frame2[3] ^ frame2[4] ^ frame2[5] ^ frame2[6];
serial->write((char*)frame2, 8);
}
this Image Illustrate what happens:recived frame
I think your code mostly looks ok. The one area that looks very suspect is your conversion of the text/string back into binary.
Since you convert your binary into a string with:
ui->termial_textEdit->append(data.toHex());
You should in theory be able to use the following to convert it back:
// Convert back...
QByteArray binaryData = QByteArray::fromHex(ui->speed_ref2_lineEdit->text().toLatin1());
// Print to debug to check it...
qDebug("d1: %02x, d2: %02x...etc...\n", binaryData[0], binaryData[1]);
// or just
qDebug() << "data:" << binaryData.toHex() << endl;
Not on my qt PC until Monday so I can't verify this code, so there may be a bug in there somewhere... I'll check it on Monday!
For serial comms I always use QByteArray's instead of char/uint8_t arrays (when using Qt) because they are so easy to use. You can re-build your array like this:
QByteArray frame2;
frame2.append((char) 0x55); // not sure you need to cast it here
frame2.append((char) 0xAA);
frame2.append((char) CMD_SPEED_REF2);
:
etc
:
If you MUST send as a char * then just do:
serial->write(frame2.data(), 8);
//or
serial->write(frame2.data(), frame2.size()); // if you want to send the whole thing

Arduino does not support messages larger than 65535 characters using websocket protocol?

I'm using the following Arduino websocket library, I had a problem when trying to send messages over than 65535 characters, I got handshake fail error.
As long as the message doesn't exceeds this length, it worked perfectly
There's a note on the main web page of the library that states:
Because of limitations of the current Arduino platform (Uno at the time of this writing),
this library does not support messages larger than 65535 characters.
In addition, this library only supports single-frame text frames.
It currently does not recognize continuation frames, binary frames, or ping/pong frames.
In the client header file named WebSocketClient.h there's the following comment:
// Don't allow the client to send big frames of data. This will flood the arduino memory and might even crash it.
#ifndef MAX_FRAME_LENGTH
#define MAX_FRAME_LENGTH 256
#endif
I'm using this old library because it is the only one worked for me on my Arduino WIFI shield, I couldn't find other libraries that support WiFi shield since most of the webscket libraries are written for Arduino Eathernet Shield support, which I don't have.
My Arduino Code is
/*DS18 Libs*/
#include <dht.h>
#include <OneWire.h>
#include <DallasTemperature.h>
/*Websocket Libs*/
#include <WebSocketServer.h>
#include <WebSocketClient.h>
#include <sha1.h>
#include <MD5.h>
#include <global.h>
#include <Base64.h>
#include <SPI.h>
#include <WiFiUdp.h>
#include <WiFiServer.h>
#include <WiFiClient.h>
#include <WiFi.h>
#include <string.h>
char ssid[] = "AMM";
char pass[] = "027274792";
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 1, 3);
WiFiClient WiFiclient;
WebSocketClient WSclient;
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
//Humidture
dht DHT;
#define DHT11_PIN 4
void setup()
{
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
//check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
/* Connect to the websocket server*/
if (WiFiclient.connect(server, 8080)) {
Serial.println("Connected");
}
else {
Serial.println("Connection failed.");
while (1) {
// Hang on failure
}
}
// Handshake with the server
WSclient.path = "/MyServer/endpoint/testtest/device/d6220ae7-caa9-48b5-92db-630c4c296ec4";
WSclient.host = "192.168.1.3:8080";
if (WSclient.handshake(WiFiclient)) {
Serial.println("Handshake successful");
}
else {
Serial.println("Handshake failed.");
while (1) {
// Hang on failure
}
}
/*DS18*/
sensors.begin();
}
void loop()
{
WSclient.sendData("{\"service_code\":\"89c4da72-a561-47db-bf62-8e63f8c4bbf0\",\"data\":[" + getHumidtureValue() + "],\"service_type\":\"TemperatureHumidityAnalysis\"}");
WSclient.sendData("{\"service_code\":\"bdc0f984-6550-4712-881f-b09071da5a73\",\"data\":" + getCBodyTempretureValue() + ",\"service_type\":\"TemperatureGaugeMonitor\"}");
//line-3 commented WSclient.sendData("{\"service_code\":\"8c212432-a86e-4c18-a956-9dc0dbb648d4\",\"data\":[" + getHumidtureValue() + "],\"service_type\":\"HumidityGaugeMonitor\"}");
}
String getCBodyTempretureValue()
{
sensors.requestTemperatures(); // Send the command to get temperatures
char charVal[10];
return dtostrf(sensors.getTempCByIndex(0), 4, 2, charVal);
}
String getHumidtureValue()
{
String str = "";
for (int i = 0; i < 2; i++)
{
int chk = DHT.read11(DHT11_PIN);
switch (chk)
{
case DHTLIB_OK:
Serial.println("OK,\t");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("Checksum error,\t");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.println("Time out error,\t");
break;
default:
Serial.println("Unknown error,\t");
break;
}
char charVal[10];
double tempF = (DHT.temperature * 9) / 5 + 32;
str = dtostrf(tempF, 3, 1, charVal);
str = str + "," + dtostrf(DHT.humidity, 3, 1, charVal);
Serial.println(str);
delay(200);
}
return str;
}
The code above works perfectly, when I uncomment the third send statement in the loop function, I got the handshake failed error.
-Is it safe to modify the value of MAX_FRAME_LENGTH for the new versions of Arduino board, considering this library is an old one?
-Is there any other libraries better than this one that can support websocket on WiFi shield?
Any solution or idea will appreciated.
Thanks in advance.
Without having looked at the code of the library it is likely not safe to change the max frame length, because the websocket protocol encodes the payload length differently depending on how long it is:
Payload length: 7 bits, 7+16 bits, or 7+64 bits.
The length of the "Payload data", in bytes: if 0-125, that is the payload length. If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length.
When the library says it doesn't support payload length above 65535 byte, it likely means that it has no implementation for the 64-bit length encoding.
After many trials and many times the program behaves very strangely, which drives me crazy, I found the problem is that I'm using too much strings in my program which makes the Arduino-Uno easily runs out of RAM.
The main reason I got handshake failed error is that the Arduino cannot read the "Sec-WebSocket-Accept" header of the handshake response message (as many other headers also) which I made sure that they are sent, by debugging code on the server.
Actually this problem and many other strange behaviors keep happening until I reduce the amount of the memory used during program run.

Serial communication not working when class is instantiated in Arduino Environment

I'm trying to write code for my Arduino Mega to communicate with ADXL345 accelerometer using c++ style library.
This is my Accelerometer.h file:
#include <Wire.h>
#define ADXL345 (0x53) // I2C Address of ADXL345 accelerometer
struct Acceleration
{
float x;
float y;
float z;
};
class Accelerometer
{
public:
Accelerometer(void); // Constructor
Acceleration readData(void); // Read sensor data
private:
char buffer[6]; // Buffer to store data (x, y, z: LSB and MSB of each)
char DATA_FORMAT; // Address of DATA_FORMAT Register
char POWER_CTL; // Address of POWER_CTL Register
char DATAX0; // Address of X-Axis LSB Data
char DATAX1; // Address of X-Axis MSB Data
char DATAY0; // Address of Y-Axis LSB Data
char DATAY1; // Address of Y-Axis MSB Data
char DATAZ0; // Address of Z-Axis LSB Data
char DATAZ1; // Address of Z-Axis MSB Data
void writeToAccelerometer(char address, char value);
void readFromAccelerometer(char address, int numOfBytes);
};
And this is my Accelerometer.cpp file:
#include "Accelerometer.h"
#include <Wire.h>
Accelerometer::Accelerometer()
{
Wire.begin(); // Initialize I2C bus
writeToAccelerometer(DATA_FORMAT, 0x01); // +/- 4g range
writeToAccelerometer(POWER_CTL, 0x08); // Measurement Mode
DATA_FORMAT = 0x31; // Address of DATA_FORMAT Register
POWER_CTL = 0x2D; // Address of POWER_CTL Register
DATAX0 = 0x32; // Address of X-Axis LSB Data
DATAX1 = 0x33; // Address of X-Axis MSB Data
DATAY0 = 0x34; // Address of Y-Axis LSB Data
DATAY1 = 0x35; // Address of Y-Axis MSB Data
DATAZ0 = 0x36; // Address of Z-Axis LSB Data
DATAZ1 = 0x37; // Address of Z-Axis MSB Data
}
void Accelerometer::writeToAccelerometer(char address, char value)
{
Wire.beginTransmission(ADXL345); // start transmission to ADXL345
Wire.write(address); // send register address
Wire.write(value); // send value to write
Wire.endTransmission(); // end transmission
}
void Accelerometer::readFromAccelerometer(char address, int numOfBytes)
{
Wire.beginTransmission(ADXL345); // start transmission to ADXL345
Wire.write(address); // send register address
Wire.endTransmission(); // end transmission
Wire.beginTransmission(ADXL345); // start transmission to ADXL345
Wire.requestFrom(ADXL345, numOfBytes); // request some bytes from device
int i = 0;
while(Wire.available()) // while there is data
{
buffer[i] = Wire.read(); // receive a byte and save it in the buffer
i++;
}
Wire.endTransmission(); // end transmission
}
Acceleration Accelerometer::readData()
{
Acceleration R;
readFromAccelerometer(DATAX0, 6); // Read data from sensor
// Merge of data and conversion to int format
int x_acceleration = (((int)buffer[1]) << 8) | buffer[0];
int y_acceleration = (((int)buffer[3]) << 8) | buffer[2];
int z_acceleration = (((int)buffer[5]) << 8) | buffer[4];
R.x = x_acceleration*0.0078;
R.y = x_acceleration*0.0078;
R.z = x_acceleration*0.0078;
return R;
}
I'm using this library im my Arduino sketch with this code:
#include <Wire.h>
#include "Accelerometer.h"
Accelerometer accel;
Acceleration Racc;
void setup()
{
Serial.begin(9600); // Start serial for outbut at 9600 bps
}
void loop()
{
Racc = accel.readData();
// Print data
Serial.print("ACCELERATION - X: ");
Serial.print( Racc.x );
Serial.print(" G / Y: ");
Serial.print( Racc.y );
Serial.print(" G / Z: ");
Serial.print( Racc.z );
Serial.print(" G\n");
delay(100);
}
This code is compilated without erros. However, because of the instantiation of Accelerometer class, Serial communication is not working (I can't see any text in Serial Monitor). When I remove the class instance of the code (letting just Serial communication in code), I can see what is print in Serial Monitor.
Does anybody have any idea about what is going on? I would appreciate any help.
As the ADXL345 can operate either SPI or I2C it needs to be configured, as such. In your case of trying to use it as I2C, the CS of the ADXL345 need to be tied to 3.3V
I2C mode is enabled if the CS pinis tied high to VDD I/O. The CS pin
should always be tied high to VDD I/O or be driven by an external
controller because there is nodefault mode if the CS pin is left
unconnected. Therefore, not taking these precautions may result in an
inability to ommunicatewith the part.
Where in your above code I do not see any pins configured as output to drive the CS.
It has been my experience that when the I2C (wire.h) library is not properly connected to a device it can be blocking. Which is similar to your described symptom here.
You may want to reference your code against others, such as https://github.com/jenschr/Arduino-libraries/tree/master/ADXL345. which appears to fully support the many features of the ADXL345 over I2C

How to read data from Arduino with Raspberry Pi with I2C

I am trying to read data from an Arduino UNO to Raspberry Pi with the python smbus module. The only documentation I could find on the smbus module was here. I am not sure what the cmd means in the module. I can use the write to send data to the Arduino. I have written two simple programs one for read and one for write
The one for write
import smbus
b = smbus.SMBus(0)
while (0==0):
var = input("Value to Write:")
b.write_byte_data(0x10,0x00,int(var))
The one for read
import smbus
bus = smbus.SMBus(0)
var = bus.read_byte_data(0x10,0x00)
print(var)
The Arduino code is
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <Wire.h>
LiquidCrystal lcd(8,9,4,5,6,7);
int a = 7;
void setup()
{
Serial.begin(9600);
lcd.begin(16,2);
// define slave address (0x2A = 42)
#define SLAVE_ADDRESS 0x10
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
// define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
void loop(){
}
// callback for received data
void receiveData(int byteCount)
{
Serial.println(byteCount);
for (int i=0;i <= byteCount;i++){
char c = Wire.read();
Serial.println(c);
}
}
// callback for sending data
void sendData()
{
Wire.write(67);
lcd.println("Send Data");
}
When I run the read program it returns "33" every time. The Arduino returns that the the sendData function is called.
I am using a Data Level Shifter and the description says it might be a little sluggish.
Has anyone gotten this to work?
I managed to initiate a communication between an Arduino and a Raspberry Pi. The two are connected using two 5k pullup resistors (see this page). The arduino write a byte on the i2c bus for each request. On the Raspberry Pi, hello is printed every second.
Arduino code:
#include <Wire.h>
#define SLAVE_ADDRESS 0x2A
void setup() {
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
Wire.onRequest(sendData);
}
void loop() {
}
char data[] = "hello";
int index = 0;
// callback for sending data
void sendData() {
Wire.write(data[index]);
++index;
if (index >= 5) {
index = 0;
}
}
Python code on the Raspberry Pi:
#!/usr/bin/python
import smbus
import time
bus = smbus.SMBus(1)
address = 0x2a
while True:
data = ""
for i in range(0, 5):
data += chr(bus.read_byte(address));
print data
time.sleep(1);
On my Raspberry Pi, the i2c bus is 1. Use the command i2c-detect -y 0 or i2c-detect -y 1 to verify if your Raspberry Pi detect your Arduino.
I know this is an old post but I have had some similar success and this seemed like a descent place to append my success.
I've been attempting to offload the calculation of high RPM to an ATTiny85 for a long time. I wanted to send the RPM on i2c request to the Pi rather than utilizing a GPIO pin interrupt and processor time on the pi. I finally accomplished this today. Here's what I came up with. Hope it can help someone. If anyone wants to critique my code, have at it!
AtTiny 85 ino code:
1 Mhz clock speed
#include <TinyWire.h>
// _____
// RST -|o AT |- VDD (1.8-5.5v)
// A3/D3 -| Tiny|- D2
// A2/D4 -| 85 |- D1 (PWM) Can use analogWrite(pin_0_or_1, 255);
// GND -|_____|- D0 SDA (PWM) on pwm pins. (8 bit resolution=0-255)
#define own_address 0x26 // I2C address - change this in arduino code if changed
#define LED_pin 4
#define hallPin 3 //Melexis US5881 Hall Effect Sensor (Put a 50K Ohm pull up resistor
// between VDD and OUT pins
bool pulseState = false;
const int sample_rate_ms = 1000;
volatile uint32_t timeCheck = 0; //uint32_t is same as "unsigned long"
volatile uint32_t pulse1 = 0; //uint32_t is same as "unsigned long"
volatile uint32_t pulse2 = 0; //uint32_t is same as "unsigned long"
volatile uint8_t i2c_regs[2] = { 0, 0 };
volatile uint16_t RPM = 0;
volatile int counter = 0; //int is same as short
void setup() {
pinMode(LED_pin, OUTPUT); // If you want to enable an LED for status.
pinMode(hallPin, INPUT);
digitalWrite(LED_pin, HIGH); // Turn on the LED to indicate alive status
delay(2000); // Leave it on for 2 seconds
digitalWrite(LED_pin, LOW); // Turn it off
TinyWire.begin( own_address );
TinyWire.onRequest( onI2CRequest );
timeCheck = millis() + sample_rate_ms; // Set a time in the future to calculate
pulse1 = micros(); // Take an initial time hack
sei(); // Enable interrupts
}
void loop() {
if (digitalRead(hallPin)!=pulseState){ // Look at the hall state
pulseState = !pulseState; // If the pin isn't what it was before
if (!pulseState){ // Check if the pin was pulled low
pulse1 = pulse2; // Start time was previous pulse
pulse2 = micros(); // End time is this pulse
++counter; // Count pulses for determining 0 RPM
delay(0.0016); // Wait for 1/600th of a second (to
// prevent bounces) Should be good up
// to about 20,000rpm. This may not be
} // necessary but it works.
}
if(millis() > timeCheck){ // Every so often (once per second in my code)
// calculate RPM or lack thereof.
timeCheck = millis() + sample_rate_ms;
if (counter < 2){ // Less than 2 pulses, it's not rotating
RPM = 0;
}else{
RPM = 60000000 / (pulse2 - pulse1); // Revs per minute at 1000000 ticks per
// second using micros()
}
i2c_regs[0] = (RPM & 0xFF00) >>8; // Prepare the two bytes to send
i2c_regs[1] = (RPM & 0x00FF); // and place them into an array
counter = 0; // Reset the counter for the next loop
}
}
void onI2CRequest() {
TinyWire.send(i2c_regs, sizeof(i2c_regs)); // Send the two bytes over i2c
}
Here's the Raspberry Pi Python 3 code:
from smbus2 import SMBus, i2c_msg
# https://pypi.org/project/smbus2/
# To install on raspberry pi execute the following:
# pip install smbus2
# or
# sudo python3 -m pip install smbus2
# or
# sudo python3 -m pip3 install smbus2
import time
from datetime import datetime, timedelta
def bytes_to_int(bytes):
result = 0
for b in bytes:
result = result * 256 + int(b)
return result
def int_to_bytes(value, length):
# This routine is unused for now
result = []
for i in range(0, length):
result.append(value >> (i * 8) & 0xff)
result.reverse()
return result
last_good_data_at = datetime.utcnow()
with SMBus(1) as bus:
address=0x26
while True:
time.sleep(0.25)
try:
read = i2c_msg.read(address, 2)
bus.i2c_rdwr(read)
bytes = list(read)
except:
bytes = []
if bytes:
last_good_data_at = datetime.utcnow()
rpm = bytes_to_int(bytes)
print(f" " + "\r", end="")
print(f"RPM: {rpm} Bytes: {bytes}" + "\r", end="")
elif datetime.utcnow() > last_good_data_at + timedelta(seconds=10):
break
print("No data received for 10 seconds.")
print("Terminating program")