1

The RadioHead library only runs on a very old core for the ATtiny85. It sends data but I would like to send something useful. The problem is I cannot read any sensors using this core. And on any other core the RadioHead library fails.

RadioHead library
ATtiny core

An old post in the Arduino forum, probably the same issue.

I would like to know what is in the DallasTemperature that conflicts with RadioHead making the code to hang.

The problem appears when I add DallasTemperature sensors(&oneWire); to the code.

// RadioHead ASK
#include <RH_ASK.h>

// DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS PB0
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Sleep
#include <avr/sleep.h>
#include <avr/wdt.h>

#ifndef cbi
  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Absolute reference PB to overcome inter-IDE issues
#define T_PIN PB1 // transmission
#define L_PIN PB3 // optional LED pin
#define BAUD 2000

// Baud rate, receiver, transmitter
RH_ASK driver(BAUD, 9, T_PIN); // pin 9 is non existent

// the Tickle structure, what a name, ugh
struct tickle {
  uint16_t id;
  uint16_t value1;
  uint16_t value2;
};

// Watchdog
volatile boolean f_wdt = 1;

ISR(WDT_vect) {
  f_wdt=1;
}

// Sleep
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// Setup for Watchdog
void setup_watchdog(int ii) {
  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}

// With set_watchdog at 8 (4 sec.) we cycle from 0 to 14
// This timer is not precise
void minute_sleep(int ms) {
  for (int c = 0; c < ms; c++) {
    for (int i = 0; i < 15; i++) {  
      system_sleep();
    }
  }
}

void setup() {
  // Debugging, if this takes less than a second, check fuses (core)
  if (!driver.init()){
    pinMode(L_PIN, OUTPUT);
    digitalWrite(L_PIN, HIGH);
    delay(500);
    digitalWrite(L_PIN, LOW);
    delay(500);
  }
  setup_watchdog(8);
  sensors.begin();
}

void loop()
{
  if (f_wdt==1) { 
    f_wdt=0;
    struct tickle package; // make a Tickle package

    package.id = 38; // hard-coded device ID
    package.value1 = analogRead(PB0); // any positive int up to 2^16
    package.value2 = analogRead(PB2); // any positive int up to 2^16

    // sending data
    driver.send((uint8_t *)&package, sizeof(package));
    driver.waitPacketSent(); // wait for it ~Barney
    minute_sleep(10); // tested: 10 was 10:30, I like
  }
}
2

I have experienced many issues when using RadioHead library on ATTiny85 together with the Arduino IDE. Your issue is not the Dallas temp sensor.

The problem lies in that RadioHead uses timer 0 on the ATTiny and changes the prescaler on the timer to match the baudrate you have requested for your tranciever. The change of prescaler changes the way Arduino IDE functions like delay()works since those also use timer 0. I believe your Dallas library depends on delay() to synchronize the signals on the 1-bus so there you have a conflict between the two libraries.

I solved this by rewriting the RadioHead RHASK files to allow for ATTiny85 timer 1 to be used instead. Here's my code. Although I use TinyHead instead of RadioHead, the change will be the same as TinyHead is a RadioHead clone.

The only change I made to RH_ASK.h is the code to define whether to use TIMER1 or not.

// Flag to indicate whether to use timer1 in attiny85.
#define RH_ASK_ATTINY_USE_TIMER1

The below changes goes into RH_ASK.cpp

First change. Update pre-scaler code and add the pre-scalers used by timer 1:

// Put these prescaler structs in PROGMEM, not on the stack
#if (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
#if defined(RH_ASK_ARDUINO_USE_TIMER2)
// Timer 2 has different prescalers
PROGMEM static const uint16_t prescalers[] = {0, 1, 8, 32, 64, 128, 256, 3333}; 
#else
  #if defined(RH_ASK_ATTINY_USE_TIMER1)
   PROGMEM static const uint16_t prescalers[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16834, 3333}; 
  #else
   PROGMEM static const uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333}; 
  #endif
#endif

Second change. This code sets up the timer 1 and goes before the existing code for ATTINY timer0 in function RH_ASK::timerSetup(). please note the "... existing code" part. The existing code for setting up timer 0 goes between the #else and the #endif

#if defined(RH_ASK_ATTINY_USE_TIMER1)
#warning RH_ASK_ATTINY_USE_TIMER1 set.
   // figure out prescaler value and counter match value
   // REVISIT: does not correctly handle 1MHz clock speeds, only works with 8MHz clocks
   // At 1MHz clock, get 1/8 of the expected baud rate
   prescaler = timerCalc(_speed, (uint8_t)-1, &nticks);
   if (!prescaler)
       return; // fault

   TCCR1 = 0; // Stop the timer
   TCNT1 = 0; // Zero the timer
   GTCCR = _BV(PSR1);  // Reset the prescaler

   // Number of ticks to count before firing interrupt
   OCR1A = uint8_t(nticks);

   TCCR1 = _BV(CTC1); // Turn on CTC mode / Output Compare pins disconnected

   // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
   TCCR1 |= prescaler; // set CS00, CS01, CS02 (other bits not needed)



   // Set mask to fire interrupt when OCIE1A bit is set in TMSK
  #ifdef TIMSK0
   // ATtiny84
   TIMSK1 |= _BV(OCIE1A);
  #else
   // ATtiny85
   TIMSK |= _BV(OCIE1A);
  #endif
#else
#warning RH_ASK_ATTINY_USE_TIMER1 not set.
   // use timer 0 (default)
   // figure out prescaler value and counter match value
   // REVISIT: does not correctly handle 1MHz clock speeds, only works with 8MHz clocks
   // At 1MHz clock, get 1/8 of the expected baud rate
   prescaler = timerCalc(_speed, (uint8_t)-1, &nticks);

... existing code

   // ATtiny85
   TIMSK |= _BV(OCIE0A);
  #endif
#endif

Third change goes where the vectors are set up. Note the added #if defined for TIMER1 and the corresponding vector. Note also that the vector for timer0 is now called TIM0_COMPA_vect in later RadioHead/TinyHead but the names TIMx and TIMERx are interchangeable.

#if (RH_PLATFORM == RH_PLATFORM_ARDUINO) 
#if defined(RH_PLATFORM_ATTINY)
 #if defined(RH_ASK_ATTINY_USE_TIMER1)
  #define RH_ASK_TIMER_VECTOR TIMER1_COMPA_vect
 #else
  #define RH_ASK_TIMER_VECTOR TIMER0_COMPA_vect
 #endif
#else // Assume Arduino Uno (328p or similar)

Mind you that I have had other issues using the DallasTempSensor library. I'm not sure whether the issue is a low quality crystal in my ATTiny or not, but I get garbage readings from my sensor. The same code works flawlessly on my Arduino Nano, so I'm currently investigating whether my ATTiny is too far off in its timings to work properly with that library. I'm also going to try the OneWire protocol to see whether that one works better. However, the above code change resolved my issues with Arduino IDE and RadioHead/TinyHead.

  • This sounds great, I thought that the ATtiny85 only had a single timer.. the TinyHead is my light copy of RadioHead and I will test your code in a new version of this library as soon as possible! – Thijs Feb 12 '18 at 12:02
  • Hi there, it has been a long time but I'm looking into this now. I cannot find any suitable place for you code to go. The #else suggests that more code will follow so it does not belong in timerSetup() in RK_ASK.cpp? – Thijs Dec 30 '18 at 8:18
  • @Thjis, I have updated the code changes above. I hope it helps. The changes goes in RH_ASK.cpp with only the actual #define in RH_ASK.h. BTW, I see the link to your GitHub was broken so I have updated the link to point to enisocha. – Octofinger Jan 4 at 21:44
  • Thank you! I have moved to GitLab: gitlab.com/thijsvanulden/TinyHead and applied for a listing on the platformio library index. I will test your code, thank you for your input!! Also, my Dallas sensor works fine for me, I use DallasTemperature from the platformio library index. – Thijs Jan 7 at 9:05
  • I made the changes and TinyHead works fine with the Timer1, thank you for that. But the the Dallas library does break the radio transmission somehow. As soon as I call sensors.requestTemperatures() I can't send any radio transmission anymore. – Thijs Jan 15 at 20:59

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.