Separating a MQ4 gas Sensor particle photon code into a .h and .cpp files - c++

I am new here. I was working with particle Photon and MQ4 I2C gas sensor.
I have a normal I2C code for this sensor
#include <application.h>
#include <spark_wiring_i2c.h>
// ADC121C_MQ4 I2C address is 0x50(80)
#define Addr 0x50
int raw_adc = 0;
double ppm = 0.0;
void setup()
{
// Set variable
Particle.variable("i2cdevice", "ADC121C_MQ4");
Particle.variable("PPM", ppm);
// Initialise I2C communication as MASTER
Wire.begin();
// Initialise serial communication, set baud rate = 9600
Serial.begin(9600);
delay(300);
}
void loop()
{
unsigned int data[2];
// Start I2C transmission
Wire.beginTransmission(Addr);
// Select data register
Wire.write(0x00);
// Stop I2C transmission
Wire.endTransmission();
// Request 2 bytes of data
Wire.requestFrom(Addr, 2);
// Read 2 bytes of data
// raw_adc msb, raw_adc lsb
if (Wire.available() == 2)
{
data[0] = Wire.read();
data[1] = Wire.read();
}
delay(300);
// Convert the data to 12-bits
raw_adc = ((data[0] & 0x0F) * 256) + data[1];
ppm = (10000 / 4096.0) * raw_adc + 200.0;
// Output data to dashboard
Particle.publish("Methane concentration : ", String(ppm));
delay(1000);
}
So I am a noob in coding and don't know how to separate this code into .cpp and .h files to get the clean code.
Please help me out, how this code can be converted into .cpp and .h files.
Thanx in advance.

Related

NRF24L01 modules not connecting - hardware or coding issue?

I am trying to transmit data from an ultrasonic sensor to an LCD screen using two NRF24L01 modules connected to two separate Arduino UNOs for a distance sensor for a bike. As I am relatively new to Arduino and initially did not know how to use the NRF24L01 module, I followed a tutorial from https://www.electroniclinic.com/nrf24l01-multiple-transmitters-and-single-receiver-for-sensor-monitoring-using-arduino/
, implemented it into my code, and it is not working. I ensured on multiple occasions that the wiring for the NRF24L01 is correct for the Arduino UNOs and attempted to change radio channels, and no use. For others from the website it appeared to be working, but for me it is not. Both programs compile just fine. Is there an issue with my code or is it possible that my NRF24L01 is nonfunctional?
Here is my code:
Transmitter:
#include <RF24Network.h>
#include <RF24Network_config.h>
#include <Sync.h>
#include <RF24.h>
#include <SPI.h>
RF24 radio(5, 4); // radio module, pins 5,4 for (CE, CSN)
RF24Network network(radio);
const uint16_t this_node = 01; //address of arduino
const uint16_t node00 = 00;
//setting up pins for each device
const int buzzerPin = 10;
const int aheadTrigPin = 9;
const int aheadEchoPin = 8;
//initialize variables for ultrasonic sensor and data
unsigned long data[3];
unsigned long aheadDistance;
unsigned long aheadDuration;
void setup() {
Serial.begin(9600);
SPI.begin();
radio.begin();
network.begin(69, this_node);
radio.setDataRate(RF24_2MBPS);
pinMode(buzzerPin, OUTPUT);
pinMode(aheadTrigPin, OUTPUT);
pinMode(aheadEchoPin, INPUT);
}
void loop() {
//clears the "trig" condition for ultrasonic sensor
digitalWrite(aheadTrigPin, LOW);
delayMicroseconds(2);
//releases sound waves from ultrasonic sensor for 10 microseconds
digitalWrite(aheadTrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(aheadTrigPin, LOW);
//reads "echo" pin to return sound wave travel time in microseconds
aheadDuration = pulseIn(aheadEchoPin, HIGH);
//calculating distance of ultrasonic sensor, in inches (distance = velocity * time)
aheadDistance = (aheadDuration * 0.034 / 2) * 2.54;
Serial.println(aheadDistance);
//activates buzzer to alert rider if danger values are met
if(aheadDistance <= 100) {
tone(buzzerPin, 255);
}
else {
noTone(buzzerPin);
}
//send data to main component
network.update();
data[0] = aheadDistance;
RF24NetworkHeader header(node00);
bool ok = network.write(header, &data, sizeof(data)); // send data
Serial.println("sent to NRF24 server");
delay(200);
}
The reason I am sending an array as the data is because I am currently working on having another transmitter to send data to a single receiver.
Receiver:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <RF24Network.h>
#include <RF24Network_config.h>
#include <Sync.h>
#include <RF24.h>
#include <SPI.h>
//sets up timer for the LCD display to constantly run
//sets up OLED screen
LiquidCrystal_I2C display(0x27,20,4);
RF24 radio (10, 9); // CE, CSN, defines new RF24 radio
RF24Network network(radio);
const uint64_t this_node = 00;
//data variables that will be collected from other arduinos
unsigned long data[3];
unsigned long aheadDistance;
unsigned long groundDistance;
unsigned long backAheadDistance;
void setup()
{
Serial.begin(9600);
display.init(); // intialize lcd
display.backlight(); //open backlight of lcd
display.clear();
//initialize starting screen
display.setCursor(0, 0);
//set up radio module (reciever)
SPI.begin();
radio.begin();
network.begin(69, this_node);
radio.setDataRate(RF24_2MBPS);
}
//method to update screen with current data values
void displayDistance() {
display.setCursor(0, 0);
display.print("Bike Sensor");
display.setCursor(0, 1);
display.print("Front: ");
display.print(aheadDistance);
display.print(" in");
display.setCursor(0, 2);
display.print("Ground: ");
display.print(groundDistance);
display.print(" in");
display.setCursor(0, 3);
display.print("Back: ");
display.print(backAheadDistance);
display.print(" in");
display.display();
}
void connectionLost() // activates when main component is unable to connect to others
{
display.clear();
display.setCursor(0, 1);
display.print("Connection");
display.setCursor(0, 2);
display.print("Lost");
display.display();
}
void loop()
{
network.update();
while(network.available()) {
RF24NetworkHeader header;
Serial.println("connection found");
network.read(header, &data, sizeof(data));
Serial.println("data recieved");
if(header.from_node == 01) {
backAheadDistance = data[0];
}
if(header.from_node == 02) {
aheadDistance = data[1];
groundDistance = data[2];
}
displayDistance();
delay(100);
}
connectionLost();
Serial.println("no connection found");
delay(200);
}
//updates OLED screen and actually displays it on the module
It’s possible that your nRF24L01 is dead. I’ve had many. Some fail. I recommend those from EByte especially ML01DP5 and ML01SP4. These are good.
Also there’s a little known hardware issue: never let the FIFO buffers remain full for over 4ms. Of course it’s hard to know. So simply flush them often as a precaution. I have fixed my code this way and now it’s robust.
Good luck!
Malcolm

ESP32 build in Arduino IDE: undefined reference to `CLASS::function' error

I tried to write an Library for the Sensirion SFM3000 Flow Sensor in the Arduino IDE for an ESP32. As long as it was one sketch, everything worked. But as I tried to seperate it into an .h and .cpp file and implemented it as a class, I get some weird error when I try to compile the sketch.
sketch\SFM3019_HSKA.cpp.o:(.literal._ZN12SFM3019_HSKA17i2c_read_flow_CRCEv+0x4): undefined reference to `SFM3019_HSKA::crc8(unsigned char, unsigned char)'
sketch\SFM3019_HSKA.cpp.o: In function `SFM3019_HSKA::i2c_read_flow_CRC()':
sketch/SFM3019_HSKA.cpp:124: undefined reference to `SFM3019_HSKA::crc8(unsigned char, unsigned char)'
sketch/SFM3019_HSKA.cpp:128: undefined reference to `SFM3019_HSKA::crc8(unsigned char, unsigned char)'
collect2.exe: error: ld returned 1 exit status
exit status 1
Fehler beim Kompilieren für das Board ESP32 Dev Module.
As I understand the error message, it occurs when the i2c_read_flow_CRC() meethod is calling the crc8() method in the last thrid of SFM3019_HSKA.cpp file. By now I don´t see an error in the syntax. But I have also no other idea on how to continue debugging...
This is the main code im trying to use the library in:
#include "SFM3019_HSKA.h"
#include <Wire.h>
SFM3019_HSKA::SensVal_s SensVal = {0, 0, 0};
SFM3019_HSKA SFM3019(0x2E); //Generate Object SFM3019 of class SFM3019_HSKA
void setup() {
// put your setup code here, to run once:
Serial.begin (115200);
delay(100);
Wire.begin (21, 22); // for ESP32: SDA= GPIO_21 /SCL= GPIO_22
SFM3019.i2c_device_check(); //checks if I2C device is available
SFM3019.i2c_write(0x3608); //write 2Byte to start continuous measurement
delay(100);
}
void loop() {
// put your main code here, to run repeatedly:
SensVal.flow = SFM3019.i2c_read_flow_CRC(); //read only Flow Bytes
Serial.println(SensVal.flow, 10);
delay(100);
SensVal = SFM3019.i2c_read_all(); //read all Sensor Bytes
Serial.print("Flow: ");
if (SensVal.flow >= 0) Serial.print(" "); //just for beauty reasons
Serial.print(SensVal.flow,10);
Serial.print(" Temp: ");
Serial.print(SensVal.temp,3);
Serial.print(" Statusword: ");
Serial.print(SensVal.statusword, HEX);
delay(400);
Serial.println();
}
and those are the library files:
SFM3019_HSKA.h
#ifndef SFM3019_HSKA_H // include guard
#define SFM3019_HSKA_H
#include "Arduino.h"
class SFM3019_HSKA {
public: //can be accessed public
SFM3019_HSKA(uint8_t i2cAddress); //Constructor
//may be nicer in private if it works anyway
typedef struct {float flow; float temp; int16_t statusword;} SensVal_s; //Struct for complete Sensor Readout
SensVal_s SensVal = {0, 0, 0}; //initialize with 0
int8_t i2c_device_check(); //function for Initialisation
int8_t i2c_write(const uint16_t SendData); //function to write 16Bit Data to sensor
SensVal_s i2c_read_all(); //function to read Flow, Temperature and Statusword
float i2c_read_flow(); //function to only read Flow
float i2c_read_flow_CRC(); //function to only read Flow with CRC check
private: //can only be accessed by functions oh same object
uint8_t SFM3019addr = 46; //SFM3019 I2C Adress: 46 / 0x2E
uint8_t crc8(const uint8_t data, uint8_t crc); //fuction for CRC confirmation
};
#endif
and the C++ file leading to the error:
SFM3019_HSKA.cpp:
#include "SFM3019_HSKA.h" //when placed in same folder
//#include <SFM3019_HSKA.h> //when placed in standard library folder
#include <Wire.h>
// some values needed for calculation of physical flow and temperature values
#define SFM3019Offset 24576
#define SFM3019ScaleFactorFlow 170.0 //needs to be a float, otherwise it will not calculate in float
#define SFM3019ScaleFactorTemp 200.0 //needs to be a float, otherwise it will not calculate in float
SFM3019_HSKA::SFM3019_HSKA(uint8_t i2cAddress) //constructor
{
//: mI2cAddress(i2cAddress)
SFM3019addr = i2cAddress;
}
/* checks if a Device at the desired address is responding with an ACK */
int8_t SFM3019_HSKA::i2c_device_check(){
Wire.beginTransmission(SFM3019addr); // Begin I2C transmission Address (i)
if (Wire.endTransmission() == 0) // Receive 0 = success (ACK response)
{
Serial.print ("Found Seosor at address");
Serial.print (SFM3019addr, DEC);
Serial.print (" (0x");
Serial.print (SFM3019addr, HEX); // 7 bit address
Serial.println (")");
return 0; //0=device sent ACK
}else{
Serial.print ("Did not receive Acknowledge from I2C address ");
Serial.print (SFM3019addr, DEC);
Serial.print (" (0x");
Serial.print (SFM3019addr, HEX); // 7 bit address
Serial.println (")");
return 1; //no ACK received
}
}
/* writes a 16bit "SendData" to I2C Bus Device "address" */
int8_t SFM3019_HSKA::i2c_write(const uint16_t SendData) {
Wire.beginTransmission(SFM3019addr);
//fill I2C outbuffer
Wire.write((SendData>>8)& 0xFF); //isolate HighByte
Wire.write(SendData & 0xFF); //isolate LowByte
//send I2C outbuffer
Wire.endTransmission();
return 0;
}
/* reads all 9 measurement bytes for flow, temp and status */
SFM3019_HSKA::SensVal_s SFM3019_HSKA::i2c_read_all(){
SensVal_s SensVal = {0}; //create empty struct
Wire.requestFrom(SFM3019addr, 9, true); // Request 9byte (3x16bit + CRC) from the sensor
//while(Wire.available()<3){}; //wait for all the data to be received //ATTENTION may be critical loop forever, however not using this may lead to an error, as the Buffer may be processed faster, then the input is read on I2C
//get Flow Bytes
int16_t flow = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
flow = flow | Wire.read(); //get Lowbyte 8LSB
byte CRCflow = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(flow, HEX); //raw values for debugging
SensVal.flow = (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions
//get Temperature Bytes
int16_t temp = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
temp = temp | Wire.read(); //get Lowbyte 8LSB
byte CRCtemp = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(temp, HEX); //raw values for debugging
SensVal.temp = temp / SFM3019ScaleFactorTemp; //calculate the flow in slm as Datasheet mentions
//get StatusWord Bytes
int16_t stat = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
stat = stat | Wire.read(); //get Lowbyte 8LSB
byte CRCstat = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(stat, HEX); //raw values for debugging
SensVal.statusword = temp / SFM3019ScaleFactorTemp; //calculate the flow in slm as Datasheet mentions
//return all data
return SensVal;
}
/* reads only first 3 bytes for flow and does NO CRC!*/
float SFM3019_HSKA::i2c_read_flow(){
Wire.requestFrom(SFM3019addr, 3, true); // Request 9byte (2x16bit + CRC) from the sensor
//while(Wire.available()<3){}; //wait for all the data to be received //ATTENTION may be critical loop forever, however not using this may lead to an error, as the Buffer may be processed faster, then the input is read on I2C
int16_t flow = Wire.read()<<8; //get Highbyte and shift 8bit to 8MSB
flow = flow | Wire.read(); //get Lowbyte 8LSB
byte CRC = Wire.read(); //get CRC Check Byte (you could do a data validy check with that)
//Serial.println(flow, HEX); //raw values for debugging
return (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions
}
/* reads only first 3 bytes for flow and DOES CRC*/
float SFM3019_HSKA::i2c_read_flow_CRC(){
Wire.requestFrom(SFM3019addr, 3, true); // Request 9byte (2x16bit + CRC) from the sensor
//while(Wire.available()<3){}; //wait for all the data to be received //ATTENTION may be critical loop forever, however not using this may lead to an error, as the Buffer may be processed faster, then the input is read on I2C
uint8_t Highbyte = Wire.read(); //get Highbyte 8MSB
uint8_t Lowbyte = Wire.read(); //get Lowbyte 8LSB
uint8_t CRC = Wire.read(); //get CRC Check Byte
//Confirm CRC
uint8_t mycrc = 0xFF; // initialize crc variable
mycrc = crc8(Highbyte, mycrc); // let first byte through CRC calculation
mycrc = crc8(Lowbyte, mycrc); // and the second byte too
if (mycrc != CRC) { // check if the calculated and the received CRC byte matches
//Serial.println("Error: wrong CRC");
return -10000; //extreme low value, so user knows somethig is wrong
} else {
//Serial.println("Success: identical CRC");
int16_t flow = (Highbyte<<8) | Lowbyte; //stack the to bytes together as signed int16
return (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions
}
}
/* calculate a CRC Byte, (Cyclic Redundancy Check) */
uint8_t crc8(const uint8_t data, uint8_t crc)
{
crc ^= data; //crc XOR data
for ( uint8_t i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ 0x31
: (crc << 1);
}
return crc;
}
I would be really thankfull for any idea on how to continue...
/* calculate a CRC Byte, (Cyclic Redundancy Check) */
uint8_t crc8(const uint8_t data, uint8_t crc)
{
crc ^= data; //crc XOR data
for ( uint8_t i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ 0x31
: (crc << 1);
}
return crc;
}
Needs to be:
/* calculate a CRC Byte, (Cyclic Redundancy Check) */
uint8_t SFM3019_HSKA::crc8(const uint8_t data, uint8_t crc)
{
crc ^= data; //crc XOR data
for ( uint8_t i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ 0x31
: (crc << 1);
}
return crc;
}
You just forgot to mark the defined method as part of the class. Simple typo error.

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;

no matching function for call unresolved overloaded function type

First I'm a newbie to C++ so my question might be already answered somewhere but I couldn't find a straightforward answer to it.
I'm creating a simple library for my hardware. I'm using a Scheduler library which is working fine on Arduino IDE (here is the example), but when I compile the code with my own IDE (Atom+PlatformIO) this error comes up:
lib\SRF08\SRF08.cpp:43:30: error: no matching function for call to 'SchedulerClass::startLoop(<unresolved overloaded functi
on type>)'
I removed some of the codes but if you need the rest I can put it.
SRF08.h
#ifndef SRF08_h
#define SRF08_h
#include "Arduino.h"
class SRF08
{
public:
//main constructor
SRF08(uint8_t address=address_1);
// init the sensor
void begin(void);
//change sensor address from oldAddress to newAddress
void changeAddress(uint16_t oldAddress, uint16_t newAddress);
// scan for a single sensor address
int8_t scanner(void);
// scan for multiple sensors and return the table of addresses
struct table_value scan_all(void);
uint16_t output_value;
void read(void);
private:
// the main I2C address of Sensor
uint16_t _address;
//read sansor value base on centimiter
};
#endif
SRF08.cpp
#include "Wire.h"
#include "SRF08.h"
// Include Scheduler since we want to manage multiple tasks.
#include "Scheduler.h"
SRF08::SRF08(uint8_t address)
{
//main constructor, address is the sensor address if u dont know it try scanner first
//address must be an integer number between 1 to 9
if (address == 1) _address = address_1;
else _address = address_1;
}
void SRF08::begin(){
//initilize I2C
Wire.begin();
output_value = 0;
Scheduler.startLoop(SRF08::read); //here is my error
}
void SRF08::read(){
int reading = 0;
// step 1: instruct sensor to read echoes
Wire.beginTransmission(_address); // transmit to device #112 (0x70)
// the address specified in the datasheet is 224 (0xE0)
// but i2c adressing uses the high 7 bits so it's 112
Wire.write(byte(0x00)); // sets register pointer to the command register (0x00)
Wire.write(byte(0x51)); // command sensor to measure in "inches" (0x50)
// use 0x51 for centimeters
// use 0x52 for ping microseconds
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(70); // datasheet suggests at least 65 milliseconds
// step 3: instruct sensor to return a particular echo reading
Wire.beginTransmission(_address); // transmit to device #112
Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02)
Wire.endTransmission(); // stop transmitting
// step 4: request reading from sensor
Wire.requestFrom(_address, 2); // request 2 bytes from slave device #112
// step 5: receive reading from sensor
if (2 <= Wire.available()) { // if two bytes were received
reading = Wire.read(); // receive high byte (overwrites previous reading)
reading = reading << 8; // shift high byte to be high 8 bits
reading |= Wire.read(); // receive low byte as lower 8 bits
output_value = reading; // print the reading
}
//yield();
}
Scheduler.h
#ifndef _SCHEDULER_H_
#define _SCHEDULER_H_
#include <Arduino.h>
extern "C" {
typedef void (*SchedulerTask)(void);
typedef void (*SchedulerParametricTask)(void *);
}
class SchedulerClass {
public:
SchedulerClass();
static void startLoop(SchedulerTask task, uint32_t stackSize = 1024);
static void start(SchedulerTask task, uint32_t stackSize = 1024);
static void start(SchedulerParametricTask task, void *data, uint32_t stackSize = 1024);
static void yield() { ::yield(); };
};
extern SchedulerClass Scheduler;
#endif
Scheduler.cpp
#include "Scheduler.h"
extern "C" {
#define NUM_REGS 10 // r4-r11, sp, pc
typedef struct CoopTask {
uint32_t regs[NUM_REGS];
void* stackPtr;
struct CoopTask* next;
struct CoopTask* prev;
} CoopTask;
static CoopTask *cur = 0;
...
void yield(void) {
coopDoYield(cur);
}
}; // extern "C"
SchedulerClass::SchedulerClass() {
coopInit();
}
static void startLoopHelper(void *taskData) {
SchedulerTask task = reinterpret_cast<SchedulerTask>(taskData);
while (true)
task();
}
void SchedulerClass::startLoop(SchedulerTask task, uint32_t stackSize) {
coopSpawn(startLoopHelper, reinterpret_cast<void *>(task), stackSize);
}
static void startTaskHelper(void *taskData) {
SchedulerTask task = reinterpret_cast<SchedulerTask>(taskData);
task();
}
void SchedulerClass::start(SchedulerTask task, uint32_t stackSize) {
coopSpawn(startTaskHelper, reinterpret_cast<void *>(task), stackSize);
}
void SchedulerClass::start(SchedulerParametricTask task, void *taskData, uint32_t stackSize) {
coopSpawn(task, taskData, stackSize);
}
SchedulerClass Scheduler;
Thanks to #Someprogrammerdude to help. I needed to declare the read function as static.
SRF08.h
#ifndef SRF08_h
#define SRF08_h
#include "Arduino.h"
class SRF08
{
public:
//main constructor
SRF08(uint8_t address=address_1);
// init the sensor
void begin(void);
//change sensor address from oldAddress to newAddress
void changeAddress(uint16_t oldAddress, uint16_t newAddress);
// scan for a single sensor address
int8_t scanner(void);
// scan for multiple sensors and return the table of addresses
struct table_value scan_all(void);
static uint16_t output_value;
static void read(void);
static uint16_t static_address;
private:
// the main I2C address of Sensor
uint16_t _address;
//read sansor value base on centimiter
};
#endif
SRF08.cpp
#include "Wire.h"
#include "SRF08.h"
// Include Scheduler since we want to manage multiple tasks.
#include "Scheduler.h"
//initilize static members
uint16_t SRF08::output_value;
uint16_t SRF08::static_address;
SRF08::SRF08(uint8_t address)
{
//main constructor, address is the sensor address if u dont know it try scanner first
//address must be an integer number between 1 to 9
if (address == 1) _address = address_1;
else _address = address_1;
static_address = _address;
//begin();
}
void SRF08::begin(){
//initilize I2C
Wire.begin();
output_value = 0;
Scheduler.startLoop(read); //here is my error
}
void SRF08::read(){
int reading = 0;
// step 1: instruct sensor to read echoes
Wire.beginTransmission(static_address); // transmit to device #112 (0x70)
// the address specified in the datasheet is 224 (0xE0)
// but i2c adressing uses the high 7 bits so it's 112
Wire.write(byte(0x00)); // sets register pointer to the command register (0x00)
Wire.write(byte(0x51)); // command sensor to measure in "inches" (0x50)
// use 0x51 for centimeters
// use 0x52 for ping microseconds
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(70); // datasheet suggests at least 65 milliseconds
// step 3: instruct sensor to return a particular echo reading
Wire.beginTransmission(static_address); // transmit to device #112
Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02)
Wire.endTransmission(); // stop transmitting
// step 4: request reading from sensor
Wire.requestFrom(static_address, 2); // request 2 bytes from slave device #112
// step 5: receive reading from sensor
if (2 <= Wire.available()) { // if two bytes were received
reading = Wire.read(); // receive high byte (overwrites previous reading)
reading = reading << 8; // shift high byte to be high 8 bits
reading |= Wire.read(); // receive low byte as lower 8 bits
output_value = reading; // print the reading
//output_value = reading;
}
yield();
}

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