Zigbee/Xbee as Receiver and Transmitter - missing packets on receiver side - arduino

My problem statement is very simple. I have one Arduino Uno and another Arduino Mega Board. Both have got Zigbee Shield mounted on them. One of them is working as Transmitter (Uno) and another (Mega) as a receiver.
Code for Tx:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("High");
delay(200);
Serial.println("Low");
delay(200);
}
Code for Rx:
char msg;
const int led = 13; //led at pin 13
void setup() {
Serial.begin(9600);//Remember that the baud must be the same on both arduinos
pinMode(led,OUTPUT);
}
void loop() {
while(Serial.available() ) {
msg=Serial.read();
if(msg=='H') {
Serial.println("Message High");
}
if(msg=='L') {
Serial.println("Message Low");
}
delay(200);
}
}
On Tx side it is sending packets serially High Low
High
Low
High
Low
High
Low
High
Low
High
Low
High
However on the receiver side, I get some packets missing. It is like
Message High
Message High
Message Low
Message High
Message High
Message High
Message Low
Message Low
Message Low
Message Low
Message Low
Message Low
Message Low
Message Low
Message Low
I would expect that it should print
Message High
Message Low
Message High
Message Low
How can i receive packets synchronously and How can i aware of any packetlos on the Rx side.
Thank you for your suggestions, corrections, comments!

First off, this statement is false: "Remember that the baud must be the same on both arduinos." You can run at different baud rates on each end of the wireless link, since the XBee modules buffer your requests. The XBee baud rate just determines the line speed of the serial connection between your host and the radio module. Everything is sent "over the air" at 250kbps.
Second, the problem is that you have a delay inside your while loop on the receiver. With that delay, you can only process one character every 200ms, so you're overflowing your buffer. The other end is sending 7 characters ("HighLow") every 400ms, and you only process 2 of them in that time.
Move the delay outside of the loop and you should be fine.

The following can be interesting to beginners
Arduino Code : Sensor + Xbee Tx
//Reference: Sparkfun
// Declaration of all necessary header file
#include "Wire.h"
#include <SPI.h>
// Declarations of Parameters
int scale_ADXL337 = 3; // 3 (±3g) for ADXL337, 200 (±200g) for ADXL377
int scale_ADXL377 = 200;// 3 (±3g) for ADXL337, 200 (±200g) for ADXL377
float rawX_ADXL337, rawY_ADXL337, rawZ_ADXL337; // Raw values for each axis of Sensor ADXL337
float rawX_ADXL377, rawY_ADXL377, rawZ_ADXL377; // Raw values for each axis of Sensor ADXL377
float scaledX_ADXL337, scaledY_ADXL337, scaledZ_ADXL337; // Scaled values for each axis of Sensor ADXL337
float scaledX_ADXL377, scaledY_ADXL377, scaledZ_ADXL377; // Scaled values for each axis of Sensor ADXL377
boolean micro_is_5V = false; // Set to true if using a 5V microcontroller such as the Arduino Uno, false if using a 3.3V microcontroller, this affects the interpretation of the sensor data
void setup()
{
// Initialize serial communication at 115200 baud
Serial.begin(9600);
//Serial.print("The Accelerometer ADXL377 and ADXL337 are connected to the MEGA BOARD");
//Serial.println();
}
// Read, scale_ADXL337, and print accelerometer data
void loop()
{
// Get raw accelerometer data for each axis
rawX_ADXL377 = analogRead(A0);
rawY_ADXL377 = analogRead(A1);
rawZ_ADXL377 = analogRead(A2);
rawX_ADXL337 = analogRead(A3);
rawY_ADXL337 = analogRead(A4);
rawZ_ADXL337 = analogRead(A5);
scaledX_ADXL377 = mapf(rawX_ADXL377, 0, 1023, -scale_ADXL377, scale_ADXL377);
scaledY_ADXL377 = mapf(rawY_ADXL377, 0, 1023, -scale_ADXL377, scale_ADXL377);
scaledZ_ADXL377 = mapf(rawZ_ADXL377, 0, 1023, -scale_ADXL377, scale_ADXL377);
scaledX_ADXL337 = mapf(rawX_ADXL337, 0, 1023, -scale_ADXL337, scale_ADXL337);
scaledY_ADXL337 = mapf(rawY_ADXL337, 0, 1023, -scale_ADXL337, scale_ADXL337);
scaledZ_ADXL337 = mapf(rawZ_ADXL337, 0, 1023, -scale_ADXL337, scale_ADXL337);
Serial.println(rawX_ADXL337);Serial.println(rawY_ADXL337);Serial.println(rawZ_ADXL337);
delay(200); // Minimum delay of 2 milliseconds between sensor reads (500 Hz)
Serial.println(rawX_ADXL377);Serial.println(rawY_ADXL377);Serial.println(rawZ_ADXL377);
delay(200); // Minimum delay of 2 milliseconds between sensor reads (500 Hz)
}
// Same functionality as Arduino's standard map function, except using floats
float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Receiver : On Aduino + XBEE Explorer (suggested by tomlogic)
long msg;
const int led = 13; //led at pin 13
void setup() {
Serial.begin(9600);//Remember that the baud must be the same on both arduinos
pinMode(led,OUTPUT);
}
void loop() {
while(Serial.available() ) {
msg=Serial.read();
//Serial.println(msg);
Serial.write(msg);
//delay(200);
}
}
Receiver on USB XBEE USB in Ubuntu
Imp : chown username /dev/ttyS1 (in my case ttyS1)
//Source : http://ubuntuforums.org/archive/index.php/t-13667.html
#include <fcntl.h>
#include <stdio.h>
#include <termios.h>
#include <stdlib.h>
#include <strings.h>
/* Change to the baud rate of the port B2400, B9600, B19200, etc */
#define SPEED B9600
/* Change to the serial port you want to use /dev/ttyUSB0, /dev/ttyS0, etc. */
#define PORT "/dev/ttyS1"
int main( ){
int fd = open( PORT, O_RDONLY | O_NOCTTY );
if (fd <0) {perror(PORT); exit(-1); }
struct termios options;
bzero(&options, sizeof(options));
options.c_cflag = SPEED | CS8 | CLOCAL | CREAD | IGNPAR;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
int r;
char buf[255];
while( 1 ){
r = read( fd, buf, 255 );
buf[r]=0;
printf( "%s", buf );
}
}

Related

warning: overflow in implicit constant conversion [-Woverflow] in Arduino Mega 2560 WI-Fi R3

i want to record a long data for like 2 to 3 hours using microcontroller Arduino Mega 2560 WI-FI R3 but I got this warning in my code
below is the picture of the warning i got.
enter image description here
the warning come up when I put the time out constant more than 30000 milliseconds
below is the code I used for the Arduino
#include "DHT.h"
// Pin Definitions
#define DHT_PIN_OUT A1
#define DHTTYPE DHT11
#define MQ3_PIN_OUT A2
#define MQ4_PIN_OUT A3
#define MQ7_PIN_OUT A4
// Global variables and defines
// object initialization
DHT dht(DHT_PIN_OUT, DHTTYPE);
// define vars for testing menu
const int timeout = 180000; //define timeout of 1 hour
char menuOption = 0;
long time0;
// Setup the essentials for your circuit to work. It runs first every time your circuit is powered with electricity.
void setup()
{
// Setup Serial which is useful for debugging
// Use the Serial Monitor to view printed messages
Serial.begin(9600);
while (!Serial) ; // wait for serial port to connect. Needed for native USB
Serial.println("start");
dht.begin();
menuOption = menu();
}
// Main logic of your circuit. It defines the interaction between the components you selected. After setup, it runs over and over again, in an eternal loop.
void loop(){
if(menuOption == '1') {
delay(500); //delay 0.5 second
// DHT11 Humidity and Temperature Sensor
// Reading humidity in %
float dhtHumidity = dht.readHumidity();
// Read temperature in Celsius, for Fahrenheit use .readTempF()
float dhtTempC = dht.readTemperature();
float Alcohol = analogRead(MQ3_PIN_OUT);
float Methane = analogRead(MQ4_PIN_OUT);
float CarbonMonoxide = analogRead(MQ7_PIN_OUT);
Serial.print(F("Humidity: ")); Serial.print(dhtHumidity); Serial.print(F("[%]\t"));
Serial.print(F("Temp: ")); Serial.print(dhtTempC); Serial.print(F("[C]\t"));
Serial.print(F("Alcohol: ")); Serial.print(Alcohol); Serial.print(F(" \t"));
Serial.print(F("Methane: ")); Serial.print(Methane); Serial.print(F(" \t"));
Serial.print(F("Carbon Monoxide: ")); Serial.println(CarbonMonoxide); Serial.println(F(" \t"));
}
if (millis() - time0 > timeout){
menuOption = menu();
}
}
// Menu function for selecting the components to be tested
// Follow serial monitor for instrcutions
char menu(){
Serial.println(F("\nSensor Array"));
Serial.println(F("Press (1) to start the sensor array"));
while (!Serial.available());
// Read data from serial monitor if received
while (Serial.available()){
char c = Serial.read();
if (isAlphaNumeric(c))
{
if(c == '1')
Serial.println(F("Now running the sensor array"));
else{
Serial.println(F("illegal input!"));
menuOption = menu();
return 0;
}
time0 = millis();
return c;
}
}
}
sorry for my bad programming and silly question, I'm new to this kind of thing. and I just found out that people usually get answers from StackOverflow, so I just wanted to try asking because I have tried to google the answer but I can't find it.

Arduino USB serial connection to Raspberry Pi (Rasbian) not initializing

I have an Arduino Nano 33 iot that outputs data via Serial at 38400 baud, connected via USB. Setup starts with Serial.Begin. The Raspberry Pi 4, running Raspian buster is set up to receive the data. It can see the correct port, /dev/ttyACM0, but nothing comes in.
I even installed the correct Arduino IDE and SAMD board package on the Raspberry Pi. It still does not find it until after the IDE uploads the replacement sketch and the CPU is reset. The IDE can grab the serial number and board type though. I can then exit out of the IDE and the Arduino is still pumping out serial to the Raspberry Pi.
The only other way to make it work is by pressing the reset button on the Arduino every time a reboot is done on the Raspberry Pi. Serial was tested on the Pi using screen.
Neither of these options are convenient. What am I missing?
/*
Connects via I2C to a CMPS14, outputs NMEA0183 HDM sentences via Serial (38400 baud)
By James Henderson, 2014, adapted to output NMEA sentences by Ian Van Schaick
*/
#include <Keyboard.h>
#include <Wire.h>
#define CMPS14_ADDRESS 0x60 // Address of CMPS14 shifted right one bit for arduino wire library
#define ANGLE_8 1 // Register to read 8bit angle from
unsigned char high_byte, low_byte, angle8;
signed char pitch, roll;
float angle16;
int fine;
float bearingH; // Holds whole degrees of bearing
float bearingL; // Holds decimal digits of bearing
int bearing;
char nbsp;
char mystring[25];
char mystring2[25];
char mystring3[25];
int software;
int cal;
unsigned int _last_status;
uint8_t checksum(char *s)
{
uint8_t c = 0;
while (*s)
c ^= *s++;
return c;
}
void CMPS14_eraseProfil()
{
Wire.beginTransmission(CMPS14_ADDRESS);
Wire.write(0x00);
Wire.write(0xE0);
_last_status = Wire.endTransmission();
delay(20); // 20ms delay after each of the three bytes send
Wire.beginTransmission(CMPS14_ADDRESS);
Wire.write(0x00);
Wire.write(0xE5);
_last_status = Wire.endTransmission();
delay(20); // 20ms delay after each of the three bytes send
Wire.beginTransmission(CMPS14_ADDRESS);
Wire.write(0x00);
Wire.write(0xE2);
_last_status = Wire.endTransmission();
delay(20); // 20ms delay after each of the three bytes send
}
//Correct heading for known deviation
int DeviationCorrect(int Head)
{
return 0;
}
void setup() {
Serial.begin(38400); // Start serial port
Wire.begin();
nbsp = 32;
// CMPS14_eraseProfil();
}
void loop() {
Wire.beginTransmission(CMPS14_ADDRESS); //starts communication with CMPS14
Wire.write(ANGLE_8); //Sends the register we wish to start reading from
Wire.endTransmission();
// Request 5 bytes from the CMPS14
// this will give us the 8 bit bearing,
// both bytes of the 16 bit bearing, pitch and roll
Wire.requestFrom(CMPS14_ADDRESS, 26);
while (Wire.available() < 26); // Wait for all bytes to come back
// software = Wire.read();
// Serial.print("Version: ");
// Serial.println(software);
angle8 = Wire.read(); // Read back the 5 bytes
high_byte = Wire.read();
low_byte = Wire.read();
pitch = Wire.read();
roll = Wire.read();
// int i = 6;
// while (i <= 25) {
// Wire.read();
// i++;
// }
//
// cal = Wire.read();
// Serial.print("Cal: ");
// Serial.println(cal);
bearing = ((high_byte << 8) + low_byte) / 10;
fine = ((high_byte << 8) + low_byte) % 10;
byte data[128] = "$HCHDM,";
data[8] = bearing;
// int deviation = 0;
//DeviationCorrect(bearing);
// bearing = bearing;
//+ deviation;
//Print out NMEA 0183 string HDM
snprintf(mystring, sizeof(mystring), "$HCHDM,%d.%d,M", bearing , fine);
uint8_t crc = checksum(mystring + 1);
Serial.print(mystring);
Serial.print("*");
if (crc < 16) Serial.print("0");
Serial.println(crc, HEX);
//Print out NMEA 0183 string XDR for Pitch
snprintf(mystring2, sizeof(mystring2), "$HCXDR,A,%d,D,PITCH", pitch);
uint8_t crc2 = checksum(mystring2 + 1);
Serial.print(mystring2);
Serial.print("*");
if(crc2 < 16) Serial.print("0");
Serial.println(crc2, HEX);
//Print out NMEA 0183 string XDR for Roll/Heel
snprintf(mystring3, sizeof(mystring3), "$HCXDR,A,%d,D,ROLL", roll);
uint8_t crc3 = checksum(mystring3 + 1);
Serial.print(mystring3);
Serial.print("*");
if(crc3 < 16) Serial.print("0");
Serial.println(crc3, HEX);
delay(100);
}

SPI Problem Arduino Mega with pressure sensor MS5803-05BA

I need your help for a project.
I have actually 2 parallel sensors of the type: MS5803-05BA, which supports I2C and SPI connection. One sensor is on I2C bus and one sensor is on SPI. They are both sending to my Arduino Mega. The I2C works perfect with short cables.
Here the datasheet of the sensor:
https://www.amsys.de/downloads/data/MS5803-05BA-AMSYS-datasheet.pdf
For some informations who wants to do the same with I2C. Here you can find a good code. (You can find the other MS580X typs there too). For the communication between the sensor and the Arduino Mega you need an logic converter like this txs0108e, which can be bought with a break out board (you need pull up resistors on the sensor side!):
https://github.com/millerlp/MS5803_05
But to my problem: I have an sensor distance for about 3-5 meters and the I2C connections doesnt work. Yes I can try to fix the pullup resistors but it doesnt worked for me (I have tried some different lower resistors between 3-10kOhm). Therefore I want to switch to the SPI bus.
I have edit the code from https://github.com/millerlp/MS5803_05, https://github.com/vic320/Arduino-MS5803-14BA and https://arduino.stackexchange.com/questions/13720/teensy-spi-and-pressure-sensor.
The File is added. (You have to put the .h and .cpp files in the folder of the arduino code (.spi).
I have problems with the code from the SPI (ccp and header). There is no right communication. I have checked my cables twice. I couldnt find a problem and the connection with the txs0108e works for parallel I2C sensor. Both sensors are working on I2C.
Here is the main code (arduino .spi) for SPI and I2C parallel:
/_____ I N C L U D E S
#include <stdio.h>
#include <math.h>
#include <SPI.h>
#include <Wire.h>
#include "MS5803_05.h"
#include "MS5803_05_SPI.h"
const int miso_port = 50; //SDI
const int mosi_port = 51; //SDO
const int sck_port = 52; //SLCK
const int slaveSelectPin = 53; // CSB
MS_5803 sensor = MS_5803(512);
MS_5803_SPI sensor_spi = MS_5803_SPI(4096, slaveSelectPin);
void setup()
{
pinMode(miso_port, INPUT);
pinMode(mosi_port, OUTPUT);
pinMode(slaveSelectPin, OUTPUT);
pinMode(sck_port, OUTPUT);
Serial.begin(9600);
//SPI BUS
if (sensor_spi.initializeMS_5803_SPI()) {
Serial.println( "MS5803 SPI CRC check OK." );
}
else {
Serial.println( "MS5803 SPI CRC check FAILED!" );
}
//I2C BUS
delay(1000);
if (sensor.initializeMS_5803()) {
Serial.println( "MS5803 I2C CRC check OK." );
}
else {
Serial.println( "MS5803 I2C CRC check FAILED!" );
}
}
void loop()
{
Serial.println("SPI Sensor first pressure [mbar], than temperature[°C]:");
sensor_spi.readSensor();
// Show pressure
Serial.print("Pressure = ");
Serial.print(sensor_spi.pressure());
Serial.println(" mbar");
// Show temperature
Serial.print("Temperature = ");
Serial.print(sensor_spi.temperature());
Serial.println("C");
////********************************************************
Serial.println("");
Serial.println("I2C Sensor first pressure [mbar], than temperature[°C]:");
sensor.readSensor();
// Show pressure
Serial.print("Pressure = ");
Serial.print(sensor.pressure());
Serial.println(" mbar");
// Show temperature
Serial.print("Temperature = ");
Serial.print(sensor.temperature());
Serial.println("C");
delay(2000);
}
}
The first connection with SPI is here (.cpp):
#include "MS5803_05_SPI.h"
#include <SPI.h>
#define CMD_RESET 0x1E // ADC reset command
#define CMD_ADC_READ 0x00 // ADC read command
#define CMD_ADC_CONV 0x40 // ADC conversion command
#define CMD_ADC_D1 0x00 // ADC D1 conversion
#define CMD_ADC_D2 0x10 // ADC D2 conversion
#define CMD_ADC_256 0x00 // ADC resolution=256
#define CMD_ADC_512 0x02 // ADC resolution=512
#define CMD_ADC_1024 0x04 // ADC resolution=1024
#define CMD_ADC_2048 0x06 // ADC resolution=2048
#define CMD_ADC_4096 0x08 // ADC resolution=4096
#define CMD_PROM_RD 0xA0 // Prom read command
#define spi_write SPI_MODE3
#define spi_write2 SPI_MODE1
// Create array to hold the 8 sensor calibration coefficients
static unsigned int sensorCoeffs[8]; // unsigned 16-bit integer (0-65535)
// D1 and D2 need to be unsigned 32-bit integers (long 0-4294967295)
static uint32_t D1 = 0; // Store uncompensated pressure value
static uint32_t D2 = 0; // Store uncompensated temperature value
// These three variables are used for the conversion steps
// They should be signed 32-bit integer initially
// i.e. signed long from -2147483648 to 2147483647
static int32_t dT = 0;
static int32_t TEMP = 0;
// These values need to be signed 64 bit integers
// (long long = int64_t)
static int64_t Offset = 0;
static int64_t Sensitivity = 0;
static int64_t T2 = 0;
static int64_t OFF2 = 0;
static int64_t Sens2 = 0;
// Some constants used in calculations below
const uint64_t POW_2_33 = 8589934592ULL; // 2^33 = 8589934592
SPISettings settings_write(500000, MSBFIRST, spi_write);
SPISettings settings_write2(500000, MSBFIRST, spi_write2);
//-------------------------------------------------
// Constructor
MS_5803_SPI::MS_5803_SPI( uint16_t Resolution, uint16_t cs) {
// The argument is the oversampling resolution, which may have values
// of 256, 512, 1024, 2048, or 4096.
_Resolution = Resolution;
//Chip Select
_cs=cs;
}
boolean MS_5803_SPI::initializeMS_5803_SPI(boolean Verbose) {
digitalWrite( _cs, HIGH );
SPI.begin();
// Reset the sensor during startup
resetSensor();
if (Verbose)
{
// Display the oversampling resolution or an error message
if (_Resolution == 256 | _Resolution == 512 | _Resolution == 1024 | _Resolution == 2048 | _Resolution == 4096){
Serial.print("Oversampling setting: ");
Serial.println(_Resolution);
} else {
Serial.println("*******************************************");
Serial.println("Error: specify a valid oversampling value");
Serial.println("Choices are 256, 512, 1024, 2048, or 4096");
Serial.println("*******************************************");
}
}
// Read sensor coefficients
for (int i = 0; i < 8; i++ )
{
SPI.beginTransaction(settings_write2);
digitalWrite(_cs, LOW); //csb_lo(); // pull CSB low
unsigned int ret;
unsigned int rC = 0;
SPI.transfer(CMD_PROM_RD + i * 2); // send PROM READ command
/*
ret = SPI.transfer(0x00); // send 0 to read the MSB
rC = 256 * ret;
ret = SPI.transfer(0x00); // send 0 to read the LSB
rC = rC + ret;
*/
// send a value of 0 to read the first byte returned:
rC = SPI.transfer( 0x00 );
rC = rC << 8;
rC |= SPI.transfer( 0x00 ); // and the second byte
sensorCoeffs[i] = (rC);
digitalWrite( _cs, HIGH );
delay(3);
}
//SPI.endTransaction(); // interrupt can now be accepted
// The last 4 bits of the 7th coefficient form a CRC error checking code.
unsigned char p_crc = sensorCoeffs[7];
// Use a function to calculate the CRC value
unsigned char n_crc = MS_5803_CRC(sensorCoeffs);
if (Verbose) {
for (int i = 0; i < 8; i++ )
{
// Print out coefficients
Serial.print("C");
Serial.print(i);
Serial.print(" = ");
Serial.println(sensorCoeffs[i]);
delay(10);
}
Serial.print("p_crc: ");
Serial.println(p_crc);
Serial.print("n_crc: ");
Serial.println(n_crc);
}
// If the CRC value doesn't match the sensor's CRC value, then the
// connection can't be trusted. Check your wiring.
if (p_crc != n_crc) {
return false;
}
// Otherwise, return true when everything checks out OK.
return true;
}
// Sends a power on reset command to the sensor.
void MS_5803_SPI::resetSensor() {
SPI.beginTransaction(settings_write);
digitalWrite(_cs, LOW); //csb_lo(); // pull CSB low to start the command
SPI.transfer(CMD_RESET); // send reset sequence
delay(3); // wait for the reset sequence timing delay(3)
digitalWrite(_cs, HIGH); //csb_hi(); // pull CSB high to finish the command
SPI.endTransaction(); // interrupt can now be accepted
}
The Code can be downloaded at: https://forum.arduino.cc/index.php?topic=670661.0
There you can find the schematic and output picture too.
Thanks a lot :).

Having hard time achieving 1 Msps with external 12bit- ADC(LTC2365) using Arduino Due

I have an LTC2365/1 Msps 12bit-ADC with SPI pins. Somehow I only could achieve a maximum of 200 Ksps with this ADC rather than something close to 1 Msps using an Arduino Due. I wonder if anyone could help me with this issue. I tried many ways but couldn't figure it out.
Datasheet for the ADC:
http://cds.linear.com/docs/en/datasheet/23656fb.pdf
Here is the code I use for Arduino:
#include <SPI.h>
const int spi_ss = 10; // set SPI SS Pin
uint8_t byte_0, byte_1; // First and second bytes read
uint16_t spi_bytes; // final 12 bit shited value
long int starttime,endtime;
long int count=0;
void setup() {
SerialUSB.begin(2000000); // begin serial and set speed
pinMode(spi_ss, OUTPUT); // Set SPI slave select pin as output
digitalWriteDirect(spi_ss, HIGH); // Make sure spi_ss is held high
SPI.begin();
SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
loop2();
SPI.endTransaction();
}
void loop2() {
starttime=millis();
endtime=starttime;
while((endtime-starttime)<=1000) {
// write the LTC CS pin low to initiate ADC sample and data transmit
digitalWriteDirect(spi_ss, LOW);
byte_0 = spi_read(0x00); // read firt 8 bits
byte_1 = spi_read(0x00); // read second 8 bits
digitalWriteDirect(spi_ss, HIGH);
// wite LTC CS pin high to stop LTC from transmitting zeros.
spi_bytes = ( ( (byte_0 <<6) ) + (byte_1 >>2) );
SerialUSB.println(spi_bytes);
count=count+1;
endtime=millis();
}
//samples per second
SerialUSB.println(count);
}
static inline uint8_t spi_read(uint8_t b) {
return SPI.transfer(b);
}
inline void digitalWriteDirect(int pin, boolean val) {
if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
else g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

Full speed on ITG3200 with Arduino

I am using a ITG3200(Sparkfun breakout board) for my project. I was trying to boost the sample rate of ITG3200 to over 2K HZ. I have already soldered two 2.2K pull-up resistors on the sensor and close the clockin pads. I encountered a few problems here. It was connected to a Arduino Uno.
The highest sample rate I can achieve was around 500 Hz. I have changed the clock to 400K. However, without doing that, I should still get something over 1000 Hz, right? I attached my code below.
Any comments or suggestions would be greatly appriecated!
#include <SPI.h>
#include <Wire.h>
// Pin definitions - Shift registers:
int enPin = 13; // Shift registers' Output Enable pin
int latchPin = 12; // Shift registers' rclk pin
int clkPin = 11; // Shift registers' srclk pin
int clrPin = 10; // shift registers' srclr pin
int datPin = 8; // shift registers' SER pin
int show = 0;
int lastMax = 0;
//This is a list of registers in the ITG-3200. Registers are parameters that determine how the sensor will behave, or they can hold data that represent the
//sensors current status.
//To learn more about the registers on the ITG-3200, download and read the datasheet.
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;//0x15
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;
//This is a list of settings that can be loaded into the registers.
//DLPF, Full Scale Register Bits
//FS_SEL must be set to 3 for proper operation
//Set DLPF_CFG to 3 for 1kHz Fint and 42 Hz Low Pass Filter
char DLPF_CFG_0 = 0;//1
char DLPF_CFG_1 = 0;//2
char DLPF_CFG_2 = 0;//4
char DLPF_FS_SEL_0 = 8;
char DLPF_FS_SEL_1 = 16;
char itgAddress = 0x69;
// Some of the math we're doing in this example requires the number of bargraph boards
// you have connected together (normally this is one, but you can have a maximum of 8).
void setup()
// Runs once upon reboot
{
// Setup shift register pins
pinMode(enPin, OUTPUT); // Enable, active low, this'll always be LOW
digitalWrite(enPin, LOW); // Turn all outputs on
pinMode(latchPin, OUTPUT); // this must be set before calling shiftOut16()
digitalWrite(latchPin, LOW); // start latch low
pinMode(clkPin, OUTPUT); // we'll control this in shiftOut16()
digitalWrite(clkPin, LOW); // start sck low
pinMode(clrPin, OUTPUT); // master clear, this'll always be HIGH
digitalWrite(clrPin, HIGH); // disable master clear
pinMode(datPin, OUTPUT); // we'll control this in shiftOut16()
digitalWrite(datPin, LOW); // start ser low
// To begin, we'll turn all LEDs on the circular bar-graph OFF
digitalWrite(latchPin, LOW); // first send latch low
shiftOut16(0x0000);
digitalWrite(latchPin, HIGH); // send latch high to indicate data is done sending
Serial.begin(230400);
//Initialize the I2C communication. This will set the Arduino up as the 'Master' device.
Wire.begin();
//Read the WHO_AM_I register and print the result
char id=0;
id = itgRead(itgAddress, 0x00);
Serial.print("ID: ");
Serial.println(id, HEX);
//Configure the gyroscope
//Set the gyroscope scale for the outputs to +/-2000 degrees per second
itgWrite(itgAddress, DLPF_FS, (DLPF_FS_SEL_0|DLPF_FS_SEL_1|DLPF_CFG_0));
//Set the sample rate to 100 hz
itgWrite(itgAddress, SMPLRT_DIV, 0);
}
void loop()
// Runs continuously after setup() ends
{
static int zero = 0;
// Create variables to hold the output rates.
int xRate, yRate, zRate;
float range = 3000.0;
int divisor;
divisor = range / 8;
//Read the x,y and z output rates from the gyroscope.
xRate = int(float(readX()) / divisor - 0.5) * -1;
yRate = int(float(readY()) / divisor - 0.5) * -1;
zRate = int(float(readZ()) / divisor - 0.5);
//Print the output rates to the terminal, seperated by a TAB character.
Serial.print(xRate);
Serial.print('\t');
Serial.print(yRate);
Serial.print('\t');
Serial.println(zRate);
Serial.print('\t');
// Serial.println(zero);
// fillTo(zRate);
//Wait 10ms before reading the values again. (Remember, the output rate was set to 100hz and 1reading per 10ms = 100hz.)
// delay(10);
}
// This function will write a value to a register on the itg-3200.
// Parameters:
// char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
// char registerAddress: The address of the register on the sensor that should be written to.
// char data: The value to be written to the specified register.
void itgWrite(char address, char registerAddress, char data)
{
//Initiate a communication sequence with the desired i2c device
Wire.beginTransmission(address);
//Tell the I2C address which register we are writing to
Wire.write(registerAddress);
//Send the value to write to the specified register
Wire.write(data);
//End the communication sequence
Wire.endTransmission();
}
//This function will read the data from a specified register on the ITG-3200 and return the value.
//Parameters:
// char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
// char registerAddress: The address of the register on the sensor that should be read
//Return:
// unsigned char: The value currently residing in the specified register
unsigned char itgRead(char address, char registerAddress)
{
//This variable will hold the contents read from the i2c device.
unsigned char data=0;
//Send the register address to be read.
Wire.beginTransmission(address);
//Send the Register Address
Wire.write(registerAddress);
//End the communication sequence.
Wire.endTransmission();
//Ask the I2C device for data
Wire.beginTransmission(address);
Wire.requestFrom(address, 1);
//Wait for a response from the I2C device
if(Wire.available()){
//Save the data sent from the I2C device
data = Wire.read();
}
//End the communication sequence.
Wire.endTransmission();
//Return the data read during the operation
return data;
}
//This function is used to read the X-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int xRate = readX();
int readX(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_XOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_XOUT_L);
return data;
}
//This function is used to read the Y-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int yRate = readY();
int readY(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_YOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_YOUT_L);
return data;
}
//This function is used to read the Z-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int zRate = readZ();
int readZ(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_ZOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_ZOUT_L);
return data;
}
void fillTo(int place) {
int ledOutput = 0;
if(place > 8)
place = 8;
if(place < -8)
place = -8;
if(place >= 0) {
for (int i = place; i >= 0; i--)
ledOutput |= 1 << i;
} else {
ledOutput = 32768;
for (int i = place; i <= 0; i++)
ledOutput |= (ledOutput >> 1);
}
// Serial.println(ledOutput);
digitalWrite(latchPin, LOW); // first send latch low
shiftOut16(ledOutput); // send the ledOutput value to shiftOut16
digitalWrite(latchPin, HIGH); // send latch high to indicate data is done sending
}
void shiftOut16(uint16_t data)
{
byte datamsb;
byte datalsb;
// Isolate the MSB and LSB
datamsb = (data & 0xFF00) >> 8; // mask out the MSB and shift it right 8 bits
datalsb = data & 0xFF; // Mask out the LSB
// First shift out the MSB, MSB first.
shiftOut(datPin, clkPin, MSBFIRST, datamsb);
// Then shift out the LSB
shiftOut(datPin, clkPin, MSBFIRST, datalsb);
}
500Hz means 2ms for each iteration of your loop() function. Your loop function is reading from Wire and writing to the Serial port, which may take more time than 2ms, depending on what you're sending and what your baud rate is.
Judging from your baud rate (230400), it may take roughly 0.5ms to send each measurement (estimated at 12 characters each) if there is no flow control from the other side. Try writing to serial less frequently to see if your performance goes up.
I tested the serial writes, the I2C port and the clock speed. Found the major issues were the redundant communication to i2c. For instance, the 6 bits data can be read in one round of i2c communication. I refered the code below:
https://raw.githubusercontent.com/ControlEverythingCommunity/ITG3200/master/Arduino/ITG-3200.ino
In addition, using Teensy is also helpful.
The speed of the output was checked by using the oscilloscope with the I2C debug function.

Resources