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);
}
  • Which arduino board do you use? The OneWire and DallasTemperature require some memory, but the RadioHead requires a lot of memory. – Jot Jan 15 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 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 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 at 15:21
  • 1
    In this line: driver.send((uint8_t *)&package, sizeof(package)); – st2000 Jan 18 at 3:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.