How display a static map on TFT in arduino - c++

I'm working on a function to display static map on TFT display (I use ESP32.). The map link is as follows (a http link):
http://osm-static-maps.herokuapp.com/?geojson=[{%22type%22:%22Point%22,%22coordinates%22:[32.37956,51.66127]}]&height=400&width=600&zoom=13&type=jpeg
and my code is as follows:
#define WIFI_SSID "<your SSID>"
#define PASSWORD "<your password>"
#define LINK "http://osm-static-maps.herokuapp.com/?geojson=[{%22type%22:%22Point%22,%22coordinates%22:[32.37956,51.66127]}]&height=400&width=600&zoom=13&type=jpeg"
#include <TJpg_Decoder.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
#define BUFSIZE 40000
uint8_t* jpgbuffer;
unsigned long jp = 0;
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) {
if ( y >= tft.height() ) return 0;
tft.pushImage(x, y, w, h, bitmap);
return 1;
}
void setup() {
jpgbuffer = (uint8_t *) malloc (BUFSIZE);
Serial.begin(115200);
tft.begin();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
WiFi.begin(WIFI_SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println();
uint32_t t = millis();
bool loaded_ok = downFile(LINK, jpgbuffer);
t = millis() - t;
if (loaded_ok) {
Serial.print("Downloaded in "); Serial.print(t); Serial.println(" ms.");
}
t = millis();
TJpgDec.drawJpg(0, 0, jpgbuffer, jp);
t = millis() - t;
Serial.print("Decoding and rendering: "); Serial.print(t); Serial.println(" ms.");
}
void loop() {
}
bool downFile(String url, uint8_t* jpgbuffer) {
Serial.println("Downloading file from " + url);
if ((WiFi.status() == WL_CONNECTED)) {
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
int total = http.getSize();
int len = total;
uint8_t buff[128] = { 0 };
WiFiClient * stream = http.getStreamPtr();
while (http.connected() && (len > 0 || len == -1)) {
size_t size = stream->available();
if (size) {
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
memcpy (jpgbuffer + jp, buff, c);
jp = jp + c;
if (len > 0) {
len -= c;
}
}
yield();
}
Serial.println();
Serial.print("[HTTP] connection closed or file end.\n");
}
}
else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
return 1;
}
Everything is OK when I use the link below, for example:
#define LINK "http://dellascolto.com/lorenz.jpg"
But when I use the link below, the Arduino hangs after uploading the code!
#define LINK "http://osm-static-maps.herokuapp.com/?geojson=[{%22type%22:%22Point%22,%22coordinates%22:[32.37956,51.66127]}]&height=400&width=600&zoom=13&type=jpeg"
Apparently, when JSON part is removed from the map link, the program runs correctly. How to solve the problem.

The image doesn't fit your buffer. It is 78886 bytes strong. You only allocate 40000 bytes.
Postpone allocation until you know the size:
total = http.getSize();
*jpgbuffer = malloc(total);
Note that in order to do so you meed pass jpgbuffer as uint8_t **.

Related

Arduino Wire requestFrom freezes

I'm trying to program a class to control the MPU6050 with the Arduino Wire library but when I run the code in my Arduino mini it freezes after a few seconds.
There is the code of the library and a test sketch:
// Include Wire Library for I2C
#include <Wire.h>
enum MPU6050_filter {_256Hz, _188Hz, _98Hz, _42Hz, _20Hz, _10Hz, _5Hz};
enum MPU6050_gyro {_250dps, _500dps, _1000dps, _2000dps};
enum MPU6050_accel {_2g, _4g, _8g, _16Hz};
class MPU6050
{
public:
MPU6050 ();
bool start (bool AD0_value);
void goToSleep ();
void stopSleeping ();
void setFilterVal (MPU6050_filter filter_val);
void setGyroRange (MPU6050_gyro range);
void setAccelRange (MPU6050_accel range);
bool dataAvailable ();
void getLastGyroData (float& gx, float& gy, float& gz);
void getRawGyroData (int& gx, int& gy, int& gz);
private:
void writeRegister (byte address, byte data);
byte readRegister (byte address);
void readData (byte start_address, byte bytes, byte* data);
float convertGyroToDPS (int gyro);
bool AD0_val;
MPU6050_filter filter;
MPU6050_accel accel_range;
MPU6050_gyro gyro_range;
unsigned long last_read;
const unsigned long min_read_time = 1;
};
MPU6050::MPU6050 () : AD0_val(false),
filter(_256Hz),
accel_range(_2g),
gyro_range(_250dps) {}
bool MPU6050::start (bool AD0_value)
{
AD0_val = AD0_value;
// init sample rate div to 0 (max sample rate)
writeRegister(0x19, 0);
// activate FIFO for gyroscope data
writeRegister(0x23, 0x70);
// clear config setup register
writeRegister(0x6B, 0);
// setup the register
writeRegister(0x37, 0x10);
// set interrupt by data ready
writeRegister(0x38, 0x01);
}
void MPU6050::goToSleep ()
{
byte prev_data = readRegister(0x6B);
prev_data = (prev_data | 0x40);
writeRegister(0x6B, prev_data);
}
void MPU6050::stopSleeping ()
{
byte prev_data = readRegister(0x6B);
prev_data = (prev_data & 0xBF);
writeRegister(0x6B, prev_data);
}
void MPU6050::setFilterVal (MPU6050_filter filter_val)
{
int val;
if (filter_val == _256Hz) val = 0;
else if (filter_val == _188Hz) val = 1;
else if (filter_val == _98Hz) val = 2;
else if (filter_val == _42Hz) val = 3;
else if (filter_val == _20Hz) val = 4;
else if (filter_val == _10Hz) val = 5;
else val = 6;
byte data = readRegister(0x1A);
data = (data & 0xF8) | (val & 0x07);
writeRegister(0x1A, data);
filter = filter_val;
}
void MPU6050::setAccelRange (MPU6050_accel range)
{
byte value;
if (range == _2g) value = 0;
else if (range == _4g) value = 1;
else if (range == _8g) value = 2;
else value = 3;
byte reg_value = readRegister(0x1C);
reg_value = (reg_value & 0xE0) | (value << 3);
writeRegister(0x1C, reg_value);
accel_range = range;
}
void MPU6050::setGyroRange (MPU6050_gyro range)
{
byte value;
if (range == _250dps) value = 0;
else if (range == _500dps) value = 1;
else if (range == _1000dps) value = 2;
else value = 3;
byte reg_value = readRegister(0x1B);
reg_value = (reg_value & 0xE0) | (value << 3);
writeRegister(0x1B, reg_value);
gyro_range = range;
}
bool MPU6050::dataAvailable ()
{
return (readRegister(0x3A) & 0x01);
}
void MPU6050::getLastGyroData (float& gx, float& gy, float& gz)
{
int raw_x, raw_y, raw_z;
getRawGyroData(raw_x, raw_y, raw_z);
gx = convertGyroToDPS(raw_x);
gy = convertGyroToDPS(raw_y);
gz = convertGyroToDPS(raw_z);
}
void MPU6050::getRawGyroData (int& gx, int& gy, int& gz)
{
byte* data = new byte[6];
readData(0x43, 6, data);
gx = data[0] << 8 | data[1];
gy = data[2] << 8 | data[3];
gz = data[4] << 8 | data[5];
delete data;
}
void MPU6050::writeRegister (byte address, byte data)
{
Wire.beginTransmission(0x68 + AD0_val);
Wire.write(address);
Wire.write(data);
Wire.endTransmission();
}
byte MPU6050::readRegister (byte address)
{
byte data_buff = 0x00;
Wire.beginTransmission(byte(0x68 + AD0_val));
//Send the requested starting register
Wire.write(address);
//End the transmission
Wire.endTransmission(false);
//Request 14 bytes from the MPU-6050
Wire.requestFrom(byte(0x68 + AD0_val), byte(0x01), byte(true));
unsigned long initial_time = millis();
//Wait until all the bytes are received
while(Wire.available() == 0 and millis() < initial_time + 5);
if (millis() < initial_time + 5)
{
// read the data
data_buff = Wire.read();
}
// end the transmission
Wire.endTransmission();
return data_buff;
}
void MPU6050::readData (byte start_address, byte bytes, byte* data)
{
Wire.beginTransmission(byte(0x68 + AD0_val));
//Send the requested starting register
Wire.write(start_address);
//End the transmission
Wire.endTransmission(false);
//Request 14 bytes from the MPU-6050
Wire.requestFrom(byte(0x68 + AD0_val), bytes, byte(true));
//Wait until all the bytes are received
while(Wire.available() < bytes);
for (int i = 0; i < bytes; i++)
data[i] = Wire.read();
Wire.endTransmission();
}
float MPU6050::convertGyroToDPS (int gyro)
{
if (gyro_range == _250dps) return float(gyro)/131.0;
else if (gyro_range == _500dps) return float(gyro)/65.5;
else if (gyro_range == _1000dps) return float(gyro)/32.8;
else return float(gyro)/16.4;
}
#define SHOW_EACH 50
MPU6050 chip;
unsigned long last_shown = 0;
unsigned this_fps = 0;
unsigned last_fps = 0;
unsigned last_time = 0;
unsigned total_fps = 0;
float g_x, g_y, g_z;
void setup()
{
Serial.begin(115200);
Serial.println("--------");
chip.setFilterVal(_256Hz);
chip.setGyroRange(_250dps);
chip.start(false);
}
void loop()
{
if (chip.dataAvailable())
chip.getLastGyroData(g_x, g_y, g_z);
++this_fps;
++total_fps;
if (millis()/1000 != last_time)
{
last_time = millis()/1000;
last_fps = this_fps;
this_fps = 0;
}
if (millis() - last_shown >= SHOW_EACH)
{
last_shown = millis();
Serial.print(g_x);
Serial.print(" ");
Serial.print(g_y);
Serial.print(" ");
Serial.print(g_y);
Serial.print(" ");
Serial.print(last_fps);
Serial.print(" ");
Serial.println(total_fps);
}
}
Some testing with Serial.println points to the function requestFrom from the Wire library. What can be the cause?
Sorry that i write this as an answer, but I can't write comments yet.
1st. There are multiple requestFrom() calls in your code, so it would be better to specify where does the problem occure exactly (if you can).
2nd. Are you completely sure that, it's the requestFrom() where your code hang. In readData() there is a while() just after requestFrom(). Maybe it hangs there, as the other device don't send enough bytes (for some reasons).
Anyway this might help a litle (link), here they recommend to always check the return value of endTransmission().

WDT reset cause 4 after reinstalling Arduino

I try to control my LED strip with an Android app.
I reinstalled the Arduino IDE since I didn't like the Windows-store version. The serial monitor broke for whatever reason so I switched back to the Windows-store version.
But now I'm getting a WDT reset error, which I can't seem to overcome.
I'm also using Adafruit_NeoPixel and wherever I put "ledstrip.begin" or "ledstrip.show" seems to break it.
#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
byte RED = 14;
byte GREEN = 12;
byte BLUE = 13;
byte PIN_COUNT = 20;
Adafruit_NeoPixel ledstrip = Adafruit_NeoPixel(PIN_COUNT, 6, NEO_RGB + NEO_KHZ800); //(num of leds, )
WiFiServer server(port);
void setup()
{
Serial.begin(115200);
delay(10);
ledstrip.begin();
Serial.print("Connecting to: ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
byte tries;
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
tries++;
Serial.println(".");
if (tries == 5)
{
Serial.println("Connection failed");
return;
}
}
Serial.println("\nWiFi connected");
server.begin();
Serial.println("Server URL: ");
Serial.print(WiFi.localIP());
}
void print_tokens(char* strings)
{
byte index = sizeof(strings);
for (int n = 0; n < index; n++)
{
Serial.println(strings[n]);
}
}
char *tokenize_request(String request)
{
char requestArray[1024];
char *ptr = NULL;
byte index = 0;
char *strings[10];
strcpy(requestArray, request.c_str());
ptr = strtok(requestArray, ";");
while (ptr != NULL) {
strings[index] = ptr;
index++;
ptr = strtok(NULL, ";");
}
return *strings;
}
void loop()
{
WiFiClient responder = server.available();
if (!responder)
{
return;
}
while (!responder.available())
{
delay(1);
}
String request = responder.readStringUntil('#');
char *strings[10] = {tokenize_request(request)};
print_tokens(*strings);
int mode = atoi(strings[0]);
int R = atoi(strings[1]);
int G = atoi(strings[2]);
int B = atoi(strings[3]);
if (mode == 1)
{
ledstrip.setPixelColor(5, R, G, B);
}
if (mode == 0)
{
ledstrip.setPixelColor(5, 0, 0, 0);
}
ledstrip.show();
delay(1);
Serial.println("------------------------------------------------------------------");
}
Serial monitor output:

Compiler optimizations and memcpy

I have an Arduino Pro Mini and an ESP32 connected by SPI. Arduino should make packets and send them to the ESP32 and vice versa.
Here are sketch for Arduino:
#include <stdint.h>
#include <time.h>
#include "SPI.h"
#define ChipSelect 10
#define Handshake 14
#define FF_PACKET_FIXED_LENGTH 5
#define SPI_BUFFER_SIZE 128
static const uint16_t crc16_table[256] = {
0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040};
// Вычисление контрольной суммы
uint16_t ffCrc16(const uint8_t *data, uint16_t data_size) {
if (!data || !data_size) {
return 0;
}
uint16_t crc = 0;
uint8_t *buf = (uint8_t *) data;
while (data_size--) {
crc = (crc >> 8) ^ crc16_table[(uint8_t)crc ^ *buf++];
}
return crc;
}
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(9600);
// set the CipSelectPin & LED as an output:
pinMode(ChipSelect, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// initialize digital pin Handsake as an input.
pinMode(Handshake, INPUT);
Serial.println("Test ESP-32");
// initialize SPI:
SPI.begin();
Serial.println("SPI Init");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
void loop() {
Serial.println("===== Loop iter start =====");
uint8_t data[50] = {0};
uint8_t *dataPtr = data;
Serial.print("sizeof(data) = ");
Serial.println(sizeof(data));
Serial.print("sizeof(dataPtr) = ");
Serial.println(sizeof(dataPtr));
uint32_t val = 1;
Serial.print("sizeof(val) = ");
Serial.println(sizeof(val));
memcpy(dataPtr, &val, 4);
dataPtr += 4;
val = (uint32_t) time(NULL);
memcpy(dataPtr, &val, 4);
dataPtr += 4;
val = 1;
memcpy(dataPtr, &val, 1);
dataPtr += 1;
val = 15;
memcpy(dataPtr, &val, 4);
dataPtr += 4;
Serial.print("data: ");
printPacket(data, 13);
uint8_t packet[50] = {0};
uint16_t packetSize = 50;
Serial.print("sizeof(packet) = ");
Serial.println(sizeof(packet));
Serial.print("sizeof(packetSize) = ");
Serial.println(sizeof(packetSize));
ffCreateCustomPacket(0xA0, data, 13, packet, &packetSize);
if (packetSize > 0) {
ffSendPacket(packet, packetSize);
}
Serial.println("===== Loop iter end =====");
delay(20000);
}
void printPacket(uint8_t *packet, uint16_t packetSize) {
uint32_t dumpSize = packetSize * 2;
char hexDump[dumpSize];
char *p = hexDump;
memset(hexDump, 0, dumpSize);
for (uint16_t i = 0; i < packetSize; ++i) {
sprintf(p, "%02x", packet[i]);
p += 2;
}
Serial.println(hexDump);
}
void ffCreateCustomPacket(uint8_t signature, uint8_t *data, uint16_t dataSize, uint8_t *buf, uint16_t *bufSize) {
uint16_t packetSize = FF_PACKET_FIXED_LENGTH + dataSize;
if (*bufSize < packetSize) {
Serial.println("Not enough buffer size!");
*bufSize = 0;
return;
}
Serial.print("data2: ");
printPacket(data, dataSize);
uint8_t *packetStart = buf;
// signature
*buf = signature;
buf++;
Serial.print("signature: ");
printPacket(packetStart, 50);
// dataSize
memcpy(buf, &dataSize, 2);
buf += 2;
Serial.print("size: ");
printPacket(packetStart, 50);
Serial.print("dataSize = ");
Serial.println(dataSize);
// data
memcpy(buf, data, dataSize);
buf += dataSize;
Serial.print("data: ");
printPacket(packetStart, 50);
// CRC
uint16_t crc = ffCrc16(packetStart, packetSize - 2);
memcpy(buf, &crc, 2);
buf += 2;
*bufSize = packetSize;
Serial.print("packet: ");
printPacket(packetStart, 50);
}
void ffSendPacket(uint8_t *packet, uint16_t packetSize) {
Serial.print("Send packet: ");
printPacket(packet, packetSize);
uint8_t spiBuffer[SPI_BUFFER_SIZE] = {0};
memcpy(spiBuffer, packet, packetSize);
SPI.transfer(spiBuffer, SPI_BUFFER_SIZE);
Serial.print("Received: ");
printPacket(spiBuffer, SPI_BUFFER_SIZE);
}
Here's the log output:
sizeof(data) = 50
sizeof(dataPtr) = 2
sizeof(val) = 4
data: 0100000000000000010f000000
sizeof(packet) = 50
sizeof(packetSize) = 2
data2: 0100000000000000010f000000
signature: a0000000000000000000000000...
size: a00d0000000000000000000000...
dataSize = 13
data: a00d0000000000000000000000...
packet: a00d0000000000000000000000000000b57d...
Send packet: a00d0000000000000000000000000000b57d
Received: 000...
Loop iter end
Actual packet should be a00d000100000000000000010f000000xxxx (xxxx - crc), but I get a00d0000000000000000000000000000b57d.
If I switch compiler flags from Os to O0 everything works fine. Are there some optimizations that cut off data memcpy and how to tell compiler not to do that?
Additional info: if I make packet array as static or allocate it on heap all works as expected too.

Adafruit SHT31-D and Raspberry Pi2 -- Unable to read data from sensor

hopefully one of you out there can help me!
I am trying to use the Adafruit SHT31-D (an i2c device) board with my Pi2. I am going off of this datasheet to guide my coding efforts. I am using Wiring Pi (wiringpi.com) to facilitate things.
I am able to successfully open a connection to the device, and sending commands seems to work fine, but I am unable to read data back! Here is the little mini library I have put together. I am hoping that one of you might have some experience with this sort of thing and be able to help me see where I've gone wrong.
To rule out any possible issues with the sensor hardware, I have tested it with my Arduino UNO and it works without issues.
Here is my C++ code:
SHT3x.h
#pragma once
/* Sensor Commands */
#define DEFAULT_SHT_ADDR 0x44
#define MEAS_HREP_STRETCH 0x2C06
#define MEAS_MREP_STRETCH 0x2C0D
#define MEAS_LREP_STRETCH 0x2C10
#define MEAS_HREP 0x2400
#define MEAS_MREP 0x240B
#define MEAS_LREP 0x2416
#include <cstdint>
class SHT3x {
public:
SHT3x(const uint8_t& i2cAddr);
float readHumidity(const uint16_t& command) const;
float readTempC(const uint16_t& command) const;
float readTempF(const uint16_t& command) const;
private:
int8_t _fd;
uint8_t _header;
uint32_t getMeasurement(const uint16_t& command) const;
void sendCommand(const uint16_t& command) const;
uint32_t receiveData(void) const;
};
SHT3x.cpp
#include <stdexcept>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include "SHT3x.h"
SHT3x::SHT3x(const uint8_t& i2cAddr) {
_fd = wiringPiI2CSetup(i2cAddr);
_header = i2cAddr << 1;
if (_fd < 0) {
throw std::runtime_error("Unable to connect");
}
}
float SHT3x::readHumidity(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_humidity = raw_data & 0xFFFF;
float humidity = 100.0 * ((float) raw_humidity / (float) 0xFFFF);
return humidity;
}
float SHT3x::readTempC(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_temp = raw_data >> 16;
float tempC = -45.0 + (175.0 * ((float) raw_temp / (float) 0xFFFF));
return tempC;
}
float SHT3x::readTempF(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_temp = raw_data >> 16;
float tempF = -49.0 + (315.0 * ((float) raw_temp / (float) 0xFFFF));
return tempF;
}
uint32_t SHT3x::getMeasurement(const uint16_t& command) const {
try {
sendCommand(command);
} catch (std::runtime_error& e) {
throw;
}
return receiveData();
}
void SHT3x::sendCommand(const uint16_t& command) const {
// break command into bytes
uint8_t MSB = command >> 8;
uint8_t LSB = command & 0xFF;
// send header
int8_t ack = wiringPiI2CWrite(_fd, _header);
// send command
ack &= wiringPiI2CWrite(_fd, MSB);
ack &= wiringPiI2CWrite(_fd, LSB);
// handle errors
if (ack) {
throw std::runtime_error("Sending command failed.");
}
}
uint32_t SHT3x::receiveData(void) const {
uint32_t data;
// send header
uint8_t read_header = _header | 0x01;
int8_t ack = wiringPiI2CWrite(_fd, read_header);
// handle errors
if (ack) throw std::runtime_error("Unable to read data.");
// read data
data = wiringPiI2CRead(_fd);
for (size_t i = 0; i < 4; i++) {
printf("Data: %d\n", data);
data <<= 8;
if (i != 1) {
data |= wiringPiI2CRead(_fd);
} else {
wiringPiI2CRead(_fd); // skip checksum
}
}
wiringPiI2CRead(_fd); // second checksum
return data;
}
The SHT31 uses 16bit read and write, rather than using 2 8bit writes you might be better off using wiringpi's 16bit write. wiringPiI2CWriteReg16(). Same thing applies to the read.
Below is a very early copy of what I've done to read the sht31-d on a PI. It has no dependencies except i2c-dev. Heater enable/disable is not working, but softreset, clearstatus, getserial & get temp/humid are all fine.
/*
* Referances
* https://www.kernel.org/doc/Documentation/i2c/dev-interface
* https://github.com/adafruit/Adafruit_SHT31
* https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity_and_Temperature_Sensors/Sensirion_Humidity_and_Temperature_Sensors_SHT3x_Datasheet_digital.pdf
*
* This depends on i2c dev lib
* sudo apt-get install libi2c-dev
*
* Below is also a good one to have, but be careful i2cdump from the below cause the sht31 interface to become unstable for me
* and requires a hard-reset to recover correctly.
* sudo apt-get install i2c-tools
*
* on PI make sure below 2 commands are in /boot/config.txt
* dtparam=i2c_arm=on
* dtparam=i2c1_baudrate=10000
* I know we are slowing down the baurate from optimal, but it seems to be the most stable setting in my testing.
* add another 0 to the above baudrate for max setting, ie dtparam=i2c1_baudrate=100000
*/
#include <linux/i2c-dev.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <elf.h>
#include <unistd.h>
#define SHT31_INTERFACE_ADDR 1
#define SHT31_DEFAULT_ADDR 0x44
#define SHT31_READ_SERIALNO 0x3780
#define SHT31_MEAS_HIGHREP_STRETCH 0x2C06 // Doesn't work on PI
#define SHT31_MEAS_MEDREP_STRETCH 0x2C0D // Seems to work on PI but shouldn't
#define SHT31_MEAS_LOWREP_STRETCH 0x2C10 // Seems to work on PI but shouldn't
#define SHT31_MEAS_HIGHREP 0x2400 // Doesn't work on PI
#define SHT31_MEAS_MEDREP 0x240B
#define SHT31_MEAS_LOWREP 0x2416
#define SHT31_READSTATUS 0xF32D
#define SHT31_CLEARSTATUS 0x3041
#define SHT31_SOFTRESET 0x30A2
#define SHT31_HEATER_ENABLE 0x306D
#define SHT31_HEATER_DISABLE 0x3066
#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
/*
* delay:
* Wait for some number of milliseconds
*********************************************************************************
*/
void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;
sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
nanosleep (&sleeper, &dummy) ;
}
/*
*
* CRC-8 formula from page 14 of SHT spec pdf
*
* Test data 0xBE, 0xEF should yield 0x92
*
* Initialization data 0xFF
* Polynomial 0x31 (x8 + x5 +x4 +1)
* Final XOR 0x00
*/
uint8_t crc8(const uint8_t *data, int len)
{
const uint8_t POLYNOMIAL = 0x31;
uint8_t crc = 0xFF;
int j;
int i;
for (j = len; j; --j ) {
crc ^= *data++;
for ( i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ POLYNOMIAL
: (crc << 1);
}
}
return crc;
}
/*
*
* buffer should return with data read, size defined by readsize
*********************************************************************************
*/
int writeandread(int fd, uint16_t sndword, uint8_t *buffer, int readsize)
{
int rtn;
uint8_t snd[3];
// Split the 16bit word into two 8 bits that are flipped.
snd[0]=(sndword >> 8) & 0xff;
snd[1]=sndword & 0xff;
rtn = write(fd, snd, 2);
if ( rtn != 2 ) {
return 1;
}
if (readsize > 0) {
delay(10);
rtn = read(fd, buffer, readsize);
if ( rtn < readsize) {
return 2;
}
}
return 0;
}
void printserialnum(int file)
{
uint8_t buf[10];
int rtn;
rtn = writeandread(file, SHT31_READ_SERIALNO, buf, 6);
if (rtn != 0)
printf("ERROR:- Get serial i2c %s failed\n",(rtn==1?"write":"read"));
else {
if (buf[2] != crc8(buf, 2) || buf[5] != crc8(buf+3, 2))
printf("WARNING:- Get serial CRC check failed, don't trust result\n");
uint32_t serialNo = ((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[3] << 8)
| (uint32_t)buf[4];
printf("Serial# = %d\n",serialNo);
}
}
void printtempandhumidity(int file)
{
uint8_t buf[10];
int rtn;
rtn = writeandread(file, SHT31_MEAS_MEDREP_STRETCH, buf, 6);
if (rtn != 0)
printf("ERROR:- Get temp/humidity i2c %s failed\n",(rtn==1?"write":"read"));
else {
if ( buf[2] != crc8(buf, 2) || buf[5] != crc8(buf+3, 2))
printf("WARNING:- Get temp/humidity CRC check failed, don't trust results\n");
uint16_t ST, SRH;
ST = buf[0];
ST <<= 8;
ST |= buf[1];
SRH = buf[3];
SRH <<= 8;
SRH |= buf[4];
double stemp = ST;
stemp *= 175;
stemp /= 0xffff;
stemp = -45 + stemp;
double stempf = ST;
stempf *= 315;
stempf /= 0xffff;
stempf = -49 + stempf;
printf("Temperature %.2fc - %.2ff\n",stemp,stempf);
double shum = SRH;
shum *= 100;
shum /= 0xFFFF;
printf("Humidity %.2f%%\n",shum);
}
}
void printBitStatus(uint16_t stat)
{
printf("Status\n");
printf(" Checksum status %d\n", CHECK_BIT(stat,0));
printf(" Last command status %d\n", CHECK_BIT(stat,1));
printf(" Reset detected status %d\n", CHECK_BIT(stat,4));
printf(" 'T' tracking alert %d\n", CHECK_BIT(stat,10));
printf(" 'RH' tracking alert %d\n", CHECK_BIT(stat,11));
printf(" Heater status %d\n", CHECK_BIT(stat,13));
printf(" Alert pending status %d\n", CHECK_BIT(stat,15));
}
void printstatus(int file)
{
uint8_t buf[10];
int rtn;
rtn = writeandread(file, SHT31_READSTATUS, buf, 3);
if (rtn != 0)
printf("ERROR:- readstatus %s failed\n",(rtn==1?"write":"read"));
else {
if ( buf[2] != crc8(buf, 2))
printf("WARNING:- Get status CRC check failed, don't trust results\n");
uint16_t stat = buf[0];
stat <<= 8;
stat |= buf[1];
printBitStatus(stat);
}
}
void clearstatus(int file)
{
if( writeandread(file, SHT31_CLEARSTATUS, NULL, 0) != 0)
printf("ERROR:- sht31 clear status failed\n");
else
printf("Clearing status - ok\n");
}
void softreset(int file)
{
if( writeandread(file, SHT31_SOFTRESET, NULL, 0) != 0)
printf("ERROR:- sht31 soft reset failed\n");
else
printf("Soft reset - ok\n");
}
void enableheater(int file)
{
if( writeandread(file, SHT31_HEATER_ENABLE, NULL, 0) != 0)
printf("ERROR:- sht31 heater enable failed\n");
else
printf("Enabiling heater - ok\n");
}
void disableheater(int file)
{
if( writeandread(file, SHT31_HEATER_DISABLE, NULL, 0) != 0)
printf("ERROR:- sht31 heater enable failed\n");
else
printf("Disableing heater - ok\n");
}
int main()
{
int file;
char filename[20];
snprintf(filename, 19, "/dev/i2c-%d", SHT31_INTERFACE_ADDR);
file = open(filename, O_RDWR);
if (file < 0) {
printf("ERROR:- Can't open %s\n",filename);
exit(1);
}
if (ioctl(file, I2C_SLAVE, SHT31_DEFAULT_ADDR) < 0) {
printf("ERROR:- Connecting to sht31 I2C address 0x%02hhx\n", SHT31_DEFAULT_ADDR);
exit(1);
}
softreset(file);
printtempandhumidity(file);
printstatus(file);
close(file);
return 0;
}

Testing arduino gps

Me and and a friend of mine are building a robot which contains a gps for arduino. We built the following circuit, to test the gps:
We're trying the following code to test the gps:
#include <SoftwareSerial.h>
#include <TinyGPS.h>
long lat,lon; // create variable for latitude and longitude object
SoftwareSerial gpsSerial(2, 3); // create gps sensor connection
TinyGPS gps; // create gps object
void setup(){
Serial.begin(9600); // connect serial
gpsSerial.begin(4800); // connect gps sensor
}
void loop(){
Serial.print("test"); //I implemented this test
while(gpsSerial.available()){ // check for gps data
Serial.print("test2"); //I implemented this test
if(gps.encode(gpsSerial.read())){ // encode gps data
Serial.print("test3"); //I implemented this test
gps.get_position(&lat,&lon); // get latitude and longitude
// display position
Serial.print("Position: ");
Serial.print("lat: ");Serial.print(lat);Serial.print(" ");// print latitude
Serial.print("lon: ");Serial.println(lon); // print longitude
}
}
}
The thing is that the serial monitor does output test number 1, but doesn't output test number 2 and number 3. So we expected the circuit we built to fail. But we double checked the wires etc. Does anybody know what the problem could be?
Any inspiration/help is welcome,
Thanks,
Justin van Til
Try this code.
#include <SoftwareSerial.h>
#include <TinyGPS.h>
TinyGPS gps;
static void print_long(long val, long invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
SoftwareSerial ss(3,4);
void setup()
{
Serial.begin(9600);
ss.begin(9600);
}
void loop()
{
long lat, lon;
int alt;
unsigned short sentences = 0, failed = 0;
gps.get_position(&lat, &lon);
alt=gps.altitude();
Serial.print("CURRENT LATITUDE & LONGITUDE:");
Serial.print(lat);
Serial.print(",");
Serial.println(lon);
Serial.print("CURRENT ALTITUDE:");
Serial.println(alt);
smartdelay(1000);
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_long (long val, long invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
smartdelay(0);
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartdelay(0);
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
smartdelay(0);
}