SpenceKonde / ATTinyCore

Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8
Other
1.53k stars 302 forks source link

ATTiny84 Issue with RF24 library #383

Closed 3xtr3m3d closed 4 years ago

3xtr3m3d commented 4 years ago

Hi

I have wired NRF24L01 module as follow

ATTiny84-|- RF24
PA6-------|- MISO
PA5-------|- MOSI
PA4-------|- SCK
PA3-------|- CSN
PA2-------|- CE

and staring library like this

#define CE_PIN 2
#define CSN_PIN 3
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);

When i use this attiny core RF module doesn't work. (tried clockwise and counter clockwise pinouts) without changing any wiring, i tried arduino 1.6.4 with damellis attiny core and RF module works.

is there anyway to get it working with this attinycore? because lot of other stuff i want is missing in working core.

Regards

SpenceKonde commented 4 years ago

I can't see why this would be the case. If anyone here is able to give some guidance about what might be wrong that would be greatly appreciated. Can you let me know where you got the version of the library you are using? Due to the ease with which repos can be forked, modified versions of libraries with the same name and same documentation have proliferated, so the name of a library does not uniquely identify what code you're using.

SpenceKonde commented 4 years ago

One quick thing - are you using the pin mapping you think you are? ATTinyCore supports two pin mappings, one with counterclockwise pin numbering, one with clockwise pin numbering (in order to provide backwards compatibility with sketches designed for either one of these - there existed cores that used both of these which predated my core). If you aren't using the one you think you are, the CE and CSN pin numbers you specify won't refer to the pins you have wired up.

As an aside, I may not be well equipped to fix this, as I was never able to get those NRF24 radios to work, period. I eventually gave up on them.

3xtr3m3d commented 4 years ago

I can't see why this would be the case. If anyone here is able to give some guidance about what might be wrong that would be greatly appreciated. Can you let me know where you got the version of the library you are using? Due to the ease with which repos can be forked, modified versions of libraries with the same name and same documentation have proliferated, so the name of a library does not uniquely identify what code you're using.

I directly downloaded the library using arduino IDE. strange thing is after i got all the functions finished using the damellis attiny core. i ve loaded the same sketch using your library and it started working. but communicating between two modules seems slow ( sometime receiver receives data sometime it doesn't) maybe its due to my code. but that problem is not in old library.

at least RF24 library works with this core.

sleemanj commented 4 years ago

sometime receiver receives data sometime it doesn't

Don't ignore that your issue could be hardware.

The NRF24L01+ modules are notorious for needing a good clean strong 3.3v power supply, the typical modules from China benefit from a decent electrolytic capacitor soldered directly on their VCC and Gnd pins.

3xtr3m3d commented 4 years ago

sometime receiver receives data sometime it doesn't

Don't ignore that your issue could be hardware.

The NRF24L01+ modules are notorious for needing a good clean strong 3.3v power supply, the typical modules from China benefit from a decent electrolytic capacitor soldered directly on their VCC and Gnd pins.

i have 10uf cap on vcc and gnd. strange thing is with the other attiny core, it works fine.

SpenceKonde commented 4 years ago

The fact that there is a difference in behavior between an identical sketch depending on which core you use is obviously a problem. But determining what is different that causes the problem is going to be a challenge here.

Can you provide example code that reproduces the problem - both receiver and sender code, hopefully something where I can just connect wires and upload code and see the problem. I ordered a batch of NRF24's that should be arriving next week, as I suspect one or both of the ones I currently have has a hardware failure, as they never worked for me in the past.

SpenceKonde commented 4 years ago

@3xtr3m3d - I have NRF24's now - Can you post the transmit and receive sketches that behave differently between the damellis core and this one? Any situation where this core breaks and the official one does not represents a bug, so if you have a reproducible issue here, I would like to fix it.

bertmelis commented 4 years ago

Dropping in here. I'm using the NRF modules too, without a (known) problem so interested in this topic.

Which library are you using?

SpenceKonde commented 4 years ago

@bertmelis thanks for stepping up and helping figure this out. I don't suppose you could share any known working sketches? (and the settings you used when compiling them) That might be helpful for @3xtr3m3d for debugging his sketch, as well as me if it turns out that there is something involving the core - certainly if, as he says, it works on the damellis core, and not mine, that's a problem (I particularly want to try to snuff out that core, as IMO it is not fit for purpose)

Regarding the settings used for compilation, by the way - I have realized that all these settings can be confusing, and that people can easily end up forgetting one of the submenus when they reopen a sketch (because I have done it, repeatedly); I am going to add some demo code showing how to add a few macros to your sketch to error out if the correct settings aren't chosen, and suggest a consistent style for listing the correct settings for your sketch.

bertmelis commented 4 years ago

~I'll post my code soon.~ Link to my code

I have to mention I use Platformio on VSCode but this should not be different from regular Arduino IDE.

Could you give a link to the NRF library you're having problems with?

Caution: I modified the NRF library a bit so it includes this framework's SPI lib header instead of the header included in the NRF lib. Otherwise it doesn't compile due to "redefinition" errors.

3xtr3m3d commented 4 years ago

@3xtr3m3d - I have NRF24's now - Can you post the transmit and receive sketches that behave differently between the damellis core and this one? Any situation where this core breaks and the official one does not represents a bug, so if you have a reproducible issue here, I would like to fix it.

Sorry for the delay. this is the sketch I have tried.

https://gist.github.com/3xtr3m3d/faef13acf206c3d45d7a49d39e2eb3a1

Floessie commented 4 years ago

Hi,

I just wanted to confirm that both pin mappings are working with the t84 and the RF24 library. The only caveat is that the RF24 module's MISO is PA6 (MOSI) on the t84 and RF24's MOSI is PA5 (MISO) on the t84 (like in @3xtr3m3d's mapping). If you use the same socket for programming the t84, take this swap into account (USBasp MISO is PA5 (MISO), USBasp MOSI is PA6 (MOSI)).

Here's my light sensor project. The prototype is running for over two years now on two AAAs. PCB designed in KiCad, manufactured by AISLER.

lo

lo

#include <avr/power.h>
#include <avr/sleep.h>

#include <util/atomic.h>

#include <EEPROM.h>

#include "nRF24L01.h"
#include "RF24.h"

//#define DEBUG
//#define WRITE_NV_SETUP

namespace
{

    struct NVSetup {
        uint8_t radio_channel;
        uint8_t rx_address[5];
        uint32_t calibrated_bandgap;
        uint8_t node_id;
    };

    NVSetup nv_setup = {
        108,
        {0xBA, 'l', 'o', 'r', 'x'},
        1098927,
        2
    };

#if defined (__AVR_ATtiny84__)
#if 0
    // Clockwise
    constexpr int CE = 7;
    constexpr int CSN = 3;
    constexpr int SENS_VCC = 10;
#else
    // Counterclockwise
    constexpr int CE = 3;
    constexpr int CSN = 7;
    constexpr int SENS_VCC = 0;
#endif
#else
    constexpr int CE = 6;
    constexpr int CSN = 7;
    constexpr int SENS_VCC = 9;
#endif

    RF24 radio(CE, CSN);

    template<typename T>
    inline T median(T array[5])
    {
        T tmp = min(array[0], array[1]);
        array[1] = max(array[0], array[1]);
        array[0] = tmp;
        tmp = min(array[3], array[4]);
        array[4] = max(array[3], array[4]);
        array[3] = max(array[0], tmp);
        array[1] = min(array[1], array[4]);
        tmp = min(array[1], array[2]);
        array[2] = max(array[1], array[2]);
        array[1] = tmp;
        tmp = min(array[2], array[3]);
        return max(array[1], tmp);
    }

    enum WdTimeout : uint8_t {
        WDT_16MS,
        WDT_32MS,
        WDT_64MS,
        WDT_125MS,
        WDT_250MS,
        WDT_500MS,
        WDT_1S,
        WDT_2S,
        WDT_4S,
        WDT_8S
    };

    void setupWatchdog(WdTimeout timeout)
    {
        uint8_t wdtcsr = timeout & 7;
        if (timeout & 8) {
            wdtcsr |= _BV(WDP3);
        }
        MCUSR &= ~_BV(WDRF);                      // Clear the WD System Reset Flag
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
            WDTCSR = _BV(WDCE) | _BV(WDE);            // Write the WD Change enable bit to enable changing the prescaler and enable system reset
            WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE);  // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU
        }
    }

    void powerDown()
    {
        const uint8_t adcsra = ADCSRA;
        ADCSRA = 0;
        set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
        sleep_enable();
        WDTCSR |= _BV(WDIE);
        sleep_mode();                        // System sleeps here
        // The WDT_vect interrupt wakes the MCU from here
        sleep_disable();                     // System continues execution here when watchdog timed out  
        WDTCSR &= ~_BV(WDIE);
        ADCSRA = adcsra;
    }

    uint16_t readVcc(uint32_t calibrated_bandgap)
    {
        // Read 1.1V reference against AVcc
#if defined (__AVR_ATtiny84__)
        ADMUX = _BV(MUX5) | _BV(MUX0);
#else
        ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
        delay(2); // Wait for Vref to settle
        ADCSRA |= _BV(ADSC); // Convert
        while (bit_is_set(ADCSRA, ADSC));
        uint32_t result = ADCL;
        result |= ADCH << 8;
        result = calibrated_bandgap / result; // Back-calculate AVcc in mV
        return result;
    }

    uint16_t readLight()
    {
        pinMode(SENS_VCC, OUTPUT);
        digitalWrite(SENS_VCC, true);
        delay(1);

        const uint16_t res = analogRead(A0);

        pinMode(SENS_VCC, INPUT);
        return res;
    }

}

void setup()
{
#ifdef WRITE_NV_SETUP
    EEPROM.put(0, nv_setup);
#endif

    if (EEPROM.read(0) != 0xFF) {
        EEPROM.get(0, nv_setup);
    }

#ifdef DEBUG
    Serial.begin(9600);

    Serial.println(F("NVSetup"));
    Serial.println(F("------------------"));
    Serial.print(F("Radio channel:      "));
    Serial.println(nv_setup.radio_channel);
    Serial.print(F("RX address:         "));
    for (uint8_t i = 0; i < sizeof(nv_setup.rx_address); ++i) {
        if (i) {
            Serial.print(' ');
        }
        Serial.print(F("0x"));
        const uint8_t v = nv_setup.rx_address[i];
        if (v < 0x10) {
            Serial.print('0');
        }
        Serial.print(v, HEX);
    }
    Serial.println();
    Serial.print(F("Calibrated bandgap: "));
    Serial.println(nv_setup.calibrated_bandgap);
    Serial.print(F("Node ID:            "));
    Serial.println(nv_setup.node_id);
#endif

    radio.begin();
    radio.enableDynamicPayloads();
    radio.setAutoAck(false);
    radio.setChannel(nv_setup.radio_channel);
    radio.setPALevel(RF24_PA_MAX);
    radio.setDataRate(RF24_250KBPS);
    radio.setAddressWidth(5);
    radio.setCRCLength(RF24_CRC_16);

    radio.stopListening();

    radio.openWritingPipe(nv_setup.rx_address);

    setupWatchdog(WDT_4S);
}

void loop() {
    struct Data {
        uint8_t id;
        uint8_t counter;
        uint16_t voltage;
        uint16_t light;
    };

    static bool first_run = true;
    static uint16_t values[5];
    static uint8_t index = 0;

    if (first_run) {
        first_run = false;
        for (uint8_t i = 0; i < 5; ++i) {
            values[i] = readVcc(nv_setup.calibrated_bandgap);
        }
    }

    values[index] = readVcc(nv_setup.calibrated_bandgap);
    index = (index + 1) % 5;

#ifdef DEBUG
    Serial.print(F("Voltage: "));
    Serial.println(median(values));
    Serial.print(F("Light: "));
    Serial.println(readLight());
#endif

    static uint8_t counter = 128;

    const Data data = {
        nv_setup.node_id,
        counter,
        median(values),
        readLight()
    };

    for (uint8_t c = 0; c < 3; ++c) {
        radio.write(&data, sizeof(data));
        delay(5);
    }

    ++counter;

    radio.powerDown();
    powerDown();
    delay(5);
    radio.powerUp();
}

ISR(WDT_vect)
{
}

Code snippets gathered from various source long time ago (mostly from Nick Gammon, as far as I recall). Works both with ATtiny84 (this core) and ATmega328 (MiniCore).

HTH, Flössie

SpenceKonde commented 4 years ago

Thanks Floessie.

As this is reported working by another user with the same library, I'm going to close this one. Please reopen with more information if this issue is still a problem - due to how much I have on my plate right now, I'm not going to work on this unless someone tells me exactly what's wrong with the core that is causing issues here.