Waterproofed water-temperature DS18B20 only returns -127 for degree in Celsius - arduino

For a project in university, I have to measure various quality of the water, including the temperature. The temperature sensor is DS18B20, and I use an Arduino Mega board to run the whole show. Individual running with DS18B20 only fails to return any meaningful number. Instead of 25C (or something like that), it returns -127.
The code below is from Dallas Temperature (with small changes, like having delay and removing some comment lines)
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 48
// 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);
void setup(void)
{
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
}
void loop(void)
{
delay(500);
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.println("DONE");
Serial.print("Temperature for the device 1 (index 0) is: ");
Serial.println(sensors.getTempCByIndex(0));
delay(2500);
}
This one is actually from the Wiki page of DFRobot (where my sensor is originated from)
#include <OneWire.h>
int DS18S20_Pin = 48; //DS18S20 Signal pin on digital 48
//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 48
void setup(void) {
Serial.begin(9600);
}
void loop(void) {
float temperature = getTemp();
Serial.println(temperature);
delay(100); //just here to slow down the output so it is easier to read
}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return -1000;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++ ) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
This specific code returns -1000 every time, which I presume is the equivalence of -127 above.
Edit: The problem was identified as faulty electric wire. Yes, hardware problem.

From the library:
// Error Codes
#define DEVICE_DISCONNECTED_C -127
https://github.com/milesburton/Arduino-Temperature-Control-Library/blob/b34be08d603242bb534e7b717dac48baf60c5113/DallasTemperature.h#L36
So you're device is not connected / not communicating. Check your wiring and your pin numbers.

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.

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 :).

How to initialize APDS-9930 ambient light / proximity sensor using ARDUINO Mega2560

I have bought a "APDS-9930" ambient light sensor, which communicates over I2C (TWI) protocol. I intend to read the the ambient light level from it, using ARDUINO Mega2560 development board. As I searched the net, I found a modified ARDUINO library, based on APDS-9960, which claims to work with APDS-9930 on ARDUINO UNO. However, when used with Mega2560, It gives me "Error initializing" error. Does anyone here know how to handle this error?
I have already used "Wire.h" library in many ways, to read "CH0 ADC data register" with address 0x14, which holds the ambient level value (according to datasheet). The code is as follows:
#define DUMP_REGS
#include <Wire.h>
#include <APDS9930.h>
// Global Variables
APDS9930 apds = APDS9930();
float ambient_light = 0; // can also be an unsigned long
uint16_t ch0 = 0;
uint16_t ch1 = 1;
void setup() {
//analogReference(EXTERNAL);
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("--------------------------------"));
Serial.println(F("APDS-9930 - Ambient light sensor"));
Serial.println(F("--------------------------------"));
// Initialize APDS-9930 (configure I2C and initial values)
//if ( apds.init() ) {
// Serial.println(F("APDS-9930 initialization complete"));
//} else {
// Serial.println(F("Something went wrong during APDS-9930 init!"));
// }
// Start running the APDS-9930 light sensor (no interrupts)
//if ( apds.enableLightSensor(false) ) {
// Serial.println(F("Light sensor is now running"));
// } else {
// Serial.println(F("Something went wrong during light sensor init!"));
// }
#ifdef DUMP_REGS
/* Register dump */
uint8_t reg;
uint8_t val;
for(reg = 0x00; reg <= 0x19; reg++) {
if( (reg != 0x10) && \
(reg != 0x11) )
{
apds.wireReadDataByte(reg, val);
Serial.print(reg, HEX);
Serial.print(": 0x");
Serial.println(val, HEX);
}
}
apds.wireReadDataByte(0x1E, val);
Serial.print(0x1E, HEX);
Serial.print(": 0x");
Serial.println(val, HEX);
#endif
// Wait for initialization and calibration to finish
delay(500);
}
void loop() {
// Read the light levels (ambient, red, green, blue)
if ( !apds.readAmbientLightLux(ambient_light) ||
!apds.readCh0Light(ch0) ||
!apds.readCh1Light(ch1) ) {
Serial.println(F("Error reading light values"));
} else {
Serial.print(F("Ambient: "));
Serial.print(ambient_light);
Serial.print(F(" Ch0: "));
Serial.print(ch0);
Serial.print(F(" Ch1: "));
Serial.println(ch1);
}
// Wait 1 second before next reading
delay(1000);
}
As discussed in the comments above, the issue is hardware related.
On the Arduino Mega 2560 board there are two resistances tying lines SDA and SCK (pins 20 and 21 on the connector) to +5V.
With those pull-up resistances, it's not possible to interface with sensors working at 3.3V directly.
The solution is to add a level shifter or remove the resistances on the board and install them externally connecting them to 5V or 3.3V as necessary depending on the sensor you want to interface to.

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.

How to change current code to read from 2 different OneWire devices?

I've been given this code which reads from a OneWire temperature device DS18b20. I'd like to add another sensor to the same pin but not quite sure how to best do it. I didn't write this code myself. I'm using an NodeMCU devkit v0.9. The code below is just a section of the full code and there are separate scripts/tabs. Let me know if I should add anything else. Any help is greatly appreciated.
#include <Arduino.h> // not automatically included?
#include <OneWire.h> // for temp sensor
#include <Wire.h> // I2C for ADC & RTC
#include <DHT.h> // Humidity sensor
#include "sens.h"
#define TEMP_PIN D2 // Where DS18B20 is connected
#define ADDR_LEN 8 // 1-Wire address length // NOT SURE WHAT THESE DO!!
#define DATA_LEN 9 // 1-Wire data length // NOT SURE WHAT THESE DO!!
#define HUMI_PIN D1 // Where the DHT11 is
#define RTC_ADDR 0x68 // Clock's I2C address
#define ADC_ADDR 0x48 // ADC's I2C address
#define SDA D3 // I2C pins
#define SCL D4
OneWire ow(TEMP_PIN); // Setup 1-Wire
byte addr[ADDR_LEN]; // To store 1-Wire address
byte data[DATA_LEN]; // To store 1-Wire data
DHT dht(HUMI_PIN, DHT11); // Setup DHT
String leading0(const int c) {
// Add a leading zero when stringifying a byte, used for the date
return (c < 10) ? ("0" + String(c)) : String(c);
}
byte bin2bcd( const byte bin ) {
// does as the name suggests, RTC uses BCD
return (bin / 10 * 16) + (bin % 10);
}
byte bcd2bin( const byte bin ) {
// does as the name suggests, RTC uses BCD
return (bin / 16 * 10) + (bin % 16);
}
void senssetup() {
// Setup sensors, called in setup()
dht.begin();
Wire.begin(SDA, SCL);
}
float gettemp() {
int i = 0;
ow.reset_search();
do {} while (!ow.search(addr) && i++ < 0xff);
// Search for 1-Wire devices
if (i == 0x100) {
if (debug) Serial.println("No devices found!");
// Nothing connected
return 0;
}
if (OneWire::crc8(addr, 7) != addr[7]) {
if (debug) Serial.println("CRC 1 failed!");
// Checksum thing when getting device's address
return -1;
}
if (addr[0] != 0x10 && addr[0] != 0x28) {
if (debug) Serial.println("Not a DS18B20");
// Wrong 1-Wire device
return -2;
}
ow.reset();
ow.select(addr);
ow.write(0x44, 0);
// HEX 44 tells it to convert temperature to readable binary
delay(1000);
// It takes ~750ms to convert data, 1s is used to be safe (1s is used in the default library too)
if (!ow.reset()) {
if (debug) Serial.println("Device not present");
// Device has disconnected or broken during conversion?
return -3;
}
ow.select(addr);
ow.write(0xbe, 0);
// Tells it we're reading
for (i = 0; i < DATA_LEN; i++) {
data[i] = ow.read(); // Read data
}
if (debug && OneWire::crc8(data, 8) != data[8])
Serial.println( "CRC Check 2 failed" );
// Checksum on data; this fails sometimes, I don't know why
// temperature is always at the right value so ignore it
int dat = ((data[1] << 8) | data[0]);
if (dat > 32767)
dat -= 65536;
// 16 bit data in 2's complement has a sign
return dat / 16.0;
// last 4 binary digits are fractional
}
You should split the search part from the getting temperature part.
NOTE: I'm not into NodeMCU, so you'll have to adapt it to that language before using it. I'd use C.
For instance, you can use a function to get all addresses of the temperature sensors and put them in an address array:
#define MAX_DEVICES 5
byte addresses[MAX_DEVICES][ADDR_LEN];
byte numOfAddresses;
void getAllAddresses()
{
numOfAddresses = 0;
ow.reset_search();
byte address[ADDR_LEN];
while (ow.search(address) && (numOfAddresses < MAX_DEVICES))
{
if ( OneWire::crc8( address, 7 ) != address[7] )
continue; // CRC 1 failed
if ( address[0] != 0x10 && address[0] != 0x28 )
continue; // Not a DS18B20
byte i;
for (i = 0; i < ADDR_LEN; i++)
addresses[numOfAddresses][i] = address[i];
numOfAddresses++;
}
if (debug)
{
Serial.print("Found ");
Serial.print(numOfAddresses);
Serial.println(" temperature sensors");
}
}
Then you can modify your function to get the temperature of the i-th sensor:
float gettemp(byte index)
{
if (index >= numOfAddresses)
{
if (debug) Serial.println( "Index not valid" );
return -200; // Don't use 0, -1, ..., since they are valid temperatures
}
ow.reset();
ow.select(addresses[index]);
ow.write(0x44, 0); // HEX 44 tells it to convert temperature to readable binary
[...]
(just replace every call to addr with a call to addresses[index].
In your code, then, instead of calling gettemp you will have to call gettemp(0) for the first sensor, gettemp(1) for the second and so on.
You will need to call getAllAddresses before the first call to gettemp, otherwise it will always return -200. You can call it at startup or every X seconds or at each measurement, that's completely up to you

Resources