1

I use a sensor to measure the temperature. This is returned as float. I feed this float using typecasting (int) to a blink function. This works fine.
But the next is step is using this same unchanged integer in a struct and send it over 433MHz using RadioHead. Here the integer is no longer an integer and it never gets sent.

When I hard code the sensor measurement value, it works. When I hard code the value in the struct it works. When I hard code the value anywhere it works.

My assumption is: when the blink works it must be an integer. When sending a hard coded integer works it must also send the measured value confirmed to be an integer. What am I missing here?

The chip is an ATtiny85
The sensor is a DS18B20
TinyHead, my light RadioHead version: https://gitlab.com/thijsvanulden/TinyHead

This is the Logic Analyzer view of what happens measured on the Data pin of the 433MHz transmitter. So something is happening at least. I can't find an Analyzer 'plugin' to translate the message coded in RadioHead, it's not Manchester encoding as it seems.

logic analyzer

Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [========  ]  75.8% (used 388 bytes from 512 bytes)
PROGRAM: [========= ]  86.4% (used 7080 bytes from 8192 bytes)

#include <Arduino.h>
#include <util/delay.h>
#include <OneWire.h>
#include <RH_ASK.h>
#include <DallasTemperature.h>

#define TICKLE_ID 0

#define ONE_WIRE_BUS 2

#define RADIOHEAD_BAUD 2000
#define RADIOHEAD_TX_PIN 1
#define RADIOHEAD_RX_PIN -1

#define LEDPIN 0

struct tickle {
  uint16_t id = TICKLE_ID;
  uint16_t value1;
  uint16_t value2;
};

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RH_ASK driver(RADIOHEAD_BAUD, RADIOHEAD_RX_PIN, RADIOHEAD_TX_PIN);

void blink(int repeat) {
  for (int i = 0; i < repeat; i++) {
    digitalWrite(LEDPIN, HIGH);
    _delay_ms(100);
    digitalWrite(LEDPIN, LOW);
    _delay_ms(100);
  }
}

void senddata(float temperatuur) {
  blink((int) temperatuur); // this always works
  struct tickle package; // make a Tickle package
  package.id = TICKLE_ID; // hard-coded device ID
  package.value1 = 0; // any positive int up to 2^16
  package.value2 = temperatuur * 100; // any positive int up to 2^16
  driver.send((uint8_t *)&package, sizeof(package));
  driver.waitPacketSent(); // wait for it ~Barney
}

void setup() {
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, HIGH);
  sensors.begin();
  driver.init();
  _delay_ms(100);
  digitalWrite(LEDPIN, LOW);
}

void loop() {
  sensors.requestTemperatures();
  _delay_ms(100);
  senddata(sensors.getTempCByIndex(0)); // hard coded 17.07 works
  _delay_ms(10000);
}

Changes made as suggested by @Jot

void senddata(float temperatuur) {
  temperatuur = (uint16_t) temperatuur;
  blink(temperatuur);
  struct tickle package; // make a Tickle package
  package.id = (uint16_t) TICKLE_ID; // hard-coded device ID
  package.value1 = (uint16_t) 0; // any positive int up to 2^16
  package.value2 = (uint16_t) 100; // any positive int up to 2^16

  blink(sizeof(package));
  driver.send((uint8_t *)&package, sizeof(package));
  driver.waitPacketSent(); // wait for it ~Barney
}

Working code, the end result
You may need to skip the Powernap code, it's a sleep library for ATtiny85. And I use the TinyHead library for 433MHz. The OneWire interaction with the sensors is 'borrowed' from http://www.nerdkits.com/forum/thread/2849/ so please send the beer and kudo's there.

#include <Arduino.h>
#include <util/delay.h>
#include <OneWire.h>
#include <RH_ASK.h>
#include <powernap.h>

#define TICKLE_ID 0
//
#define ONE_WIRE_BUS 2
//
#define RADIOHEAD_BAUD 2000
#define RADIOHEAD_TX_PIN 1
#define RADIOHEAD_RX_PIN -1

#define LEDPIN 0

struct tickle {
  uint16_t id = TICKLE_ID;
  uint16_t value1;
  uint16_t value2;
};

Napper napper;
OneWire TemperatureSensor(2);
RH_ASK driver(RADIOHEAD_BAUD, RADIOHEAD_RX_PIN, RADIOHEAD_TX_PIN);

void blink(int repeat) {
  for (int i = 0; i < repeat; i++) {
    digitalWrite(LEDPIN, HIGH);
    napper.delay(100);
    digitalWrite(LEDPIN, LOW);
    napper.delay(100);
  }
}

void senddata(float temperatuur) {
  blink((int) temperatuur);
  struct tickle package; // make a Tickle package
  package.id = TICKLE_ID; // hard-coded device ID
  package.value1 = 0; // any positive int up to 2^16
  package.value2 = temperatuur * 100; // any positive int up to 2^16

  blink(sizeof(package));
  driver.send((uint8_t *)&package, sizeof(package));
  driver.waitPacketSent(); // wait for it ~Barney
}

void setup() {
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, HIGH);
  driver.init();
  napper.setup();
  napper.delay(100);
  digitalWrite(LEDPIN, LOW);
}

void loop() {
  byte i;
  byte data[12];
  int16_t raw;
  float celsius, fahrenheit;

  TemperatureSensor.reset();       // reset one wire buss
  TemperatureSensor.skip();        // select only device
  TemperatureSensor.write(0x44);   // start conversion

  delay(1000);                     // wait for the conversion

  TemperatureSensor.reset();
  TemperatureSensor.skip();
  TemperatureSensor.write(0xBE);   // Read Scratchpad
  for ( i = 0; i < 9; i++) {       // 9 bytes
    data[i] = TemperatureSensor.read();
  }

  // Convert the data to actual temperature
  raw = (data[1] << 8) | data[0];
  celsius = (float)raw / 16.0;
  napper.delay(100);
  senddata(celsius);
  napper.napminutes(1);
}
21
  • Which arduino board do you use? The OneWire and DallasTemperature require some memory, but the RadioHead requires a lot of memory.
    – Jot
    Jan 15, 2019 at 22:21
  • 1
    Is it possible you think you are sending three bytes of data while you might actually be sending six bytes of data.
    – st2000
    Jan 16, 2019 at 5:24
  • 1
    @Thijs I think I did not read it very well and was rude, my apologies. Can you do a test: fool the compiler to make it think that getTempCByIndex is used, but send a constant. In the function senddata: convert it: uint16_t t = temperature; get rid of it: t /= 10000; add a constant: t += 1789; fill the package: package.value2 = t;. Linking the getTempCByIndex function into the binary might be too much for the ram usage.
    – Jot
    Jan 16, 2019 at 21:08
  • 1
    Casting values is like telling the compiler "don't mind what these memory locations were, now I want you to treat them differently". So, you used 6 bytes of memory to store 3 uint16_t values. Then you told the compiler to look at the 6 bytes of memory as if they were uint8_t values. You further cemented your intentions by specifying the "size" of the values. That is, the size of function returned that you had used 6 bytes of memory for the storage of the 3 uint16_t variables or, as you casted them, 6 uint8_t variables.
    – st2000
    Jan 17, 2019 at 15:21
  • 1
    In this line: driver.send((uint8_t *)&package, sizeof(package));
    – st2000
    Jan 18, 2019 at 3:22

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.