Commit 1c89b946 authored by TMRh20's avatar TMRh20

Merge remote-tracking branch 'origin/Updates'

parents 17323323 0153c713
...@@ -26,7 +26,22 @@ void RF24::csn(bool mode) ...@@ -26,7 +26,22 @@ void RF24::csn(bool mode)
#endif #endif
#endif #endif
#if !defined (__arm__) || defined (CORE_TEENSY)
#if defined (RF24_TINY)
if (ce_pin != csn_pin) {
digitalWrite(csn_pin,mode);
}
else {
if (mode == HIGH) {
PORTB |= (1<<PINB2); // SCK->CSN HIGH
delayMicroseconds(100); // allow csn to settle.
}
else {
PORTB &= ~(1<<PINB2); // SCK->CSN LOW
delayMicroseconds(20); // allow csn to settle
}
}
#else if !defined (__arm__) || defined (CORE_TEENSY)
digitalWrite(csn_pin,mode); digitalWrite(csn_pin,mode);
#endif #endif
...@@ -36,7 +51,8 @@ void RF24::csn(bool mode) ...@@ -36,7 +51,8 @@ void RF24::csn(bool mode)
void RF24::ce(bool level) void RF24::ce(bool level)
{ {
digitalWrite(ce_pin,level); //Allow for 3-pin use on ATTiny
if (ce_pin != csn_pin) digitalWrite(ce_pin,level);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -420,6 +436,7 @@ void RF24::printDetails(void) ...@@ -420,6 +436,7 @@ void RF24::printDetails(void)
printf_P(PSTR("CRC Length\t = %S\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()])); printf_P(PSTR("CRC Length\t = %S\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()]));
printf_P(PSTR("PA Power\t = %S\r\n"),pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()])); printf_P(PSTR("PA Power\t = %S\r\n"),pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()]));
#endif #endif
} }
#endif #endif
...@@ -428,7 +445,7 @@ void RF24::printDetails(void) ...@@ -428,7 +445,7 @@ void RF24::printDetails(void)
void RF24::begin(void) void RF24::begin(void)
{ {
// Initialize pins // Initialize pins
pinMode(ce_pin,OUTPUT); if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT);
#if defined(__arm__) && ! defined( CORE_TEENSY ) #if defined(__arm__) && ! defined( CORE_TEENSY )
SPI.begin(csn_pin); // Using the extended SPI features of the DUE SPI.begin(csn_pin); // Using the extended SPI features of the DUE
...@@ -438,7 +455,7 @@ void RF24::begin(void) ...@@ -438,7 +455,7 @@ void RF24::begin(void)
ce(LOW); ce(LOW);
//csn(HIGH); //csn(HIGH);
#else #else
pinMode(csn_pin,OUTPUT); if (ce_pin != csn_pin) pinMode(csn_pin,OUTPUT);
SPI.begin(); SPI.begin();
ce(LOW); ce(LOW);
csn(HIGH); csn(HIGH);
...@@ -504,7 +521,9 @@ void RF24::begin(void) ...@@ -504,7 +521,9 @@ void RF24::begin(void)
void RF24::startListening(void) void RF24::startListening(void)
{ {
#if !defined (RF24_TINY)
powerUp(); powerUp();
#endif
write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX)); write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
...@@ -545,6 +564,14 @@ void RF24::stopListening(void) ...@@ -545,6 +564,14 @@ void RF24::stopListening(void)
} }
//flush_rx(); //flush_rx();
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
#if defined (RF24_TINY)
// for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle
if (ce_pin == csn_pin) {
powerDown();
powerUp();
}
#endif
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0 write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0
delayMicroseconds(100); delayMicroseconds(100);
......
...@@ -10,21 +10,50 @@ version 2 as published by the Free Software Foundation. ...@@ -10,21 +10,50 @@ version 2 as published by the Free Software Foundation.
The ATtiny85 will transmit a counting number every second starting from 1. The ATtiny85 will transmit a counting number every second starting from 1.
The ATtiny85 uses the tiny-core by CodingBadly (https://code.google.com/p/arduino-tiny/) The ATtiny85 uses the tiny-core by CodingBadly (https://code.google.com/p/arduino-tiny/)
When direct use of 3v3 does not work (UNO boards have bad 3v3 line) use 5v with LED (1.8V ~ 2.2V drop) When direct use of 3v3 does not work (UNO boards have bad 3v3 line) use 5v with LED (1.8V ~ 2.2V drop)
For low power consumption solutions floating pins (SCK and MOSI) should be pulled high or low with eg. 10K
** Hardware configuration ** ** Hardware configuration **
ATtiny25/45/85 Pin map ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 4
+-\/-+
NC PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 --- LED --- 5V
nRF24L01 CE, pin3 --- PB3 2| |7 PB2 --- nRF24L01 SCK, pin5
nRF24L01 CSN, pin4 --- PB4 3| |6 PB1 --- nRF24L01 MOSI, pin7
nRF24L01 GND, pin1 --- GND 4| |5 PB0 --- nRF24L01 MISO, pin6
+----+
ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 3 => PB3 and PB4 are free to use for application
Circuit idea from http://nerdralph.blogspot.ca/2014/01/nrf24l01-control-with-3-attiny85-pins.html
Original RC combination was 1K/100nF. 22K/10nF combination worked better.
For best settletime delay value in RF24::csn() the timingSearch3pin.ino scatch can be used.
This configuration is enabled when CE_PIN and CSN_PIN are equal, e.g. both 3
Because CE is always high the power consumption is higher than for 5 pins solution
^^
+-\/-+ nRF24L01 CE, pin3 ------| //
PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 ------x----------x--|<|-- 5V
NC PB3 2| |7 PB2 --- nRF24L01 SCK, pin5 --|<|---x-[22k]--| LED
NC PB4 3| |6 PB1 --- nRF24L01 MOSI, pin7 1n4148 |
nRF24L01 GND, pin1 -x- GND 4| |5 PB0 --- nRF24L01 MISO, pin6 |
| +----+ |
|-----------------------------------------------||----x-- nRF24L01 CSN, pin4
10nF
ATtiny24/44/84 Pin map with CE_PIN 8 and CSN_PIN 7
Schematic provided and successfully tested by Carmine Pastore (https://github.com/Carminepz)
+-\/-+ +-\/-+
Reset/Ain0 (D 5) PB5 1|o |8 Vcc (3v3 or -- LED -- 5v) nRF24L01 VCC, pin2 --- VCC 1|o |14 GND --- nRF24L01 GND, pin1
nRF24L01 CE, Pin3 - Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1 - nRF24L01 SCK, pin5 PB0 2| |13 AREF
nRF24L01 CSN, Pin4 - Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1 - nRF24L01 MOSI, pin7 PB1 3| |12 PA1
GND 4| |5 PB0 (D 0) pwm0 - nRF24L01 MISO, pin6 PB3 4| |11 PA2 --- nRF24L01 CE, pin3
CE and CSN are configurable PB2 5| |10 PA3 --- nRF24L01 CSN, pin4
PA7 6| |9 PA4 --- nRF24L01 SCK, pin5
nRF24L01 MOSI, pin7 --- PA6 7| |8 PA5 --- nRF24L01 MISO, pin6
+----+
*/ */
// CE and CSN are configurable, specified values for ATtiny85 as connected above
#define CE_PIN 3 #define CE_PIN 3
#define CSN_PIN 4 #define CSN_PIN 4
//#define CSN_PIN 3 // uncomment for ATtiny85 3 pins solution
#include "RF24.h" #include "RF24.h"
......
/*
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
timingSearch3pin.ino by tong67 ( https://github.com/tong67 )
This sketch can be used to determine the best settleTime values to use in RF24::csn().
The used settleTimeValues are 100/20. Depend on used RC combiniation and voltage drop by LED.
It is setup to be completely selfcontained, copied defines and code from RF24 library.
The ATtiny85 uses the tiny-core by CodingBadly (https://code.google.com/p/arduino-tiny/)
(Intermediate) results are written to TX (PB3, pin 2). For schematic see rf24ping85.ino
*/
// nRF24L01.h copy
/* Memory Map */
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
#define DYNPD 0x1C
#define FEATURE 0x1D
/* Bit Mnemonics */
#define MASK_RX_DR 6
#define MASK_TX_DS 5
#define MASK_MAX_RT 4
#define EN_CRC 3
#define CRCO 2
#define PWR_UP 1
#define PRIM_RX 0
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
#define AW 0
#define ARD 4
#define ARC 0
#define PLL_LOCK 4
#define RF_DR 3
#define RF_PWR 6
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
#define RX_P_NO 1
#define TX_FULL 0
#define PLOS_CNT 4
#define ARC_CNT 0
#define TX_REUSE 6
#define FIFO_FULL 5
#define TX_EMPTY 4
#define RX_FULL 1
#define RX_EMPTY 0
#define DPL_P5 5
#define DPL_P4 4
#define DPL_P3 3
#define DPL_P2 2
#define DPL_P1 1
#define DPL_P0 0
#define EN_DPL 2
#define EN_ACK_PAY 1
#define EN_DYN_ACK 0
/* Instruction Mnemonics */
#define R_REGISTER 0x00
#define W_REGISTER 0x20
#define REGISTER_MASK 0x1F
#define ACTIVATE 0x50
#define R_RX_PL_WID 0x60
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define W_ACK_PAYLOAD 0xA8
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF
/* Non-P omissions */
#define LNA_HCURR 0
/* P model memory Map */
#define RPD 0x09
#define W_TX_PAYLOAD_NO_ACK 0xB0
/* P model bit Mnemonics */
#define RF_DR_LOW 5
#define RF_DR_HIGH 3
#define RF_PWR_LOW 1
#define RF_PWR_HIGH 2
/****************************************************************************/
//ATTiny support code pulled in from https://github.com/jscrane/RF24
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// see http://gammon.com.au/spi
# define DI 0 // D0, pin 5 Data In
# define DO 1 // D1, pin 6 Data Out (this is *not* MOSI)
# define USCK 2 // D2, pin 7 Universal Serial Interface clock
# define SS 3 // D3, pin 2 Slave Select
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
// these depend on the core used (check pins_arduino.h)
// this is for jeelabs' one (based on google-code core)
# define DI 4 // PA6
# define DO 5 // PA5
# define USCK 6 // PA4
# define SS 3 // PA7
#endif
#if defined (ARDUINO) && !defined (__arm__)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#define RF24_TINY
#else
// #include <SPI.h>
#endif
#endif
#if defined(RF24_TINY)
#include <stdio.h>
#include <Arduino.h>
#include <avr/pgmspace.h>
#define SPI_CLOCK_DIV4 0x00
#define SPI_CLOCK_DIV16 0x01
#define SPI_CLOCK_DIV64 0x02
#define SPI_CLOCK_DIV128 0x03
#define SPI_CLOCK_DIV2 0x04
#define SPI_CLOCK_DIV8 0x05
#define SPI_CLOCK_DIV32 0x06
//#define SPI_CLOCK_DIV64 0x07
#define SPI_MODE0 0x00
#define SPI_MODE1 0x04
#define SPI_MODE2 0x08
#define SPI_MODE3 0x0C
#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
class SPIClass {
public:
static byte transfer(byte _data);
// SPI Configuration methods
inline static void attachInterrupt();
inline static void detachInterrupt(); // Default
static void begin(); // Default
static void end();
// static void setBitOrder(uint8_t);
// static void setDataMode(uint8_t);
// static void setClockDivider(uint8_t);
};
extern SPIClass SPI;
#endif /* RF24_TINY */
#if defined(RF24_TINY)
void SPIClass::begin() {
digitalWrite(SS, HIGH);
pinMode(USCK, OUTPUT);
pinMode(DO, OUTPUT);
pinMode(SS, OUTPUT);
pinMode(DI, INPUT);
USICR = _BV(USIWM0);
}
byte SPIClass::transfer(byte b) {
USIDR = b;
USISR = _BV(USIOIF);
do
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
while ((USISR & _BV(USIOIF)) == 0);
return USIDR;
}
void SPIClass::end() {}
#endif /* RF24_TINY */
/****************************************************************************/
uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
uint8_t csn_pin; /**< SPI Chip select */
uint8_t csnHighSettle = 255;
uint8_t csnLowSettle = 255;
/****************************************************************************/
void ce(bool level) {
if (ce_pin != csn_pin) digitalWrite(ce_pin,level);
}
/****************************************************************************/
void setCsnHighSettle(uint8_t level) {
csnHighSettle = level;
}
/****************************************************************************/
void setCsnLowSettle(uint8_t level) {
csnLowSettle = level;
}
/****************************************************************************/
void csn(bool mode) {
if (ce_pin != csn_pin) {
digitalWrite(csn_pin,mode);
} else {
if (mode == HIGH) {
PORTB |= (1<<PINB2); // SCK->CSN HIGH
delayMicroseconds(csnHighSettle); // allow csn to settle
} else {
PORTB &= ~(1<<PINB2); // SCK->CSN LOW
delayMicroseconds(csnLowSettle); // allow csn to settle
}
}
}
/****************************************************************************/
uint8_t read_register(uint8_t reg)
{
csn(LOW);
SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
uint8_t result = SPI.transfer(0xff);
csn(HIGH);
return result;
}
/****************************************************************************/
uint8_t write_register2(uint8_t reg, uint8_t value)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
SPI.transfer(value);
csn(HIGH);
return status;
}
/****************************************************************************/
#if defined(RF24_TINY)
#define CE_PIN 3
#define CSN_PIN 3
#else
#define CE_PIN 7
#define CSN_PIN 8
#endif
#define MAX_HIGH 100
#define MAX_LOW 100
#define MINIMAL 8
void setup(void) {
uint8_t status;
// start serial port and SPI
Serial.begin(9600);
SPI.begin();
// configure ce and scn as output when used
ce_pin = CE_PIN;
csn_pin = CSN_PIN;
setCsnHighSettle(MAX_HIGH);
setCsnLowSettle(MAX_LOW);
// csn is used in SPI transfers. Set to LOW at start and HIGH after transfer. Set to HIGH to reflect no transfer active
// SPI command are accepted in Power Down state.
// ce represent PRX (LOW) or PTX (HIGH) mode apart from register settings. Start in PRX mode.
ce(LOW);
csn(HIGH);
// nRF24L01 goes from to Power Down state 100ms after Power on Reset ( Vdd > 1.9V) or when PWR_UP is 0 in config register
// Goto Power Down state (Powerup or force) and set in transmit mode
write_register2(CONFIG, read_register(CONFIG) & ~_BV(PWR_UP) & ~_BV(PRIM_RX));
delay(100);
// Goto Standby-I
// Technically we require 4.5ms Tpd2stby+ 14us as a worst case. We'll just call it 5ms for good measure.
// WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
write_register2(CONFIG, read_register(CONFIG) | _BV(PWR_UP));
delay(5) ;
// Goto Standby-II
ce(HIGH);
Serial.print("Scanning for optimal setting time for scn");
}
void loop(void) {
uint8_t status;
uint8_t i;
uint8_t j;
uint8_t k;
bool success = true;
uint8_t csnHigh = MAX_HIGH;
uint8_t csnLow = MAX_LOW;
uint8_t bottom_success;
bool bottom_found;
uint8_t value[] = {5,10};
uint8_t limit[] = {MAX_HIGH,MAX_LOW};
uint8_t advice[] = {MAX_HIGH,MAX_LOW};
// check max values give correct behavior
for (k=0;k<2;k++) {
bottom_found = false;
bottom_success = 0;
while(bottom_success < 255) {
setCsnHighSettle(limit[0]);
setCsnLowSettle(limit[1]);
// check current values
i = 0;
while(i<255 & success) {
for (j=0;j<2;j++) {
write_register2(EN_AA, value[j]);
status = read_register(EN_AA);
if (value[j] != status) {
success = false;
}
}
i++;
}
// process result of current values
if (!success) {
Serial.print("Settle NOK. csnHigh=");
Serial.print(limit[0],DEC);
Serial.print(" csnLow=");
Serial.println(limit[1],DEC);
limit[k]++;
bottom_found = true;
bottom_success = 0;
success = true;
} else {
Serial.print("Settle OK. csnHigh=");
Serial.print(limit[0],DEC);
Serial.print(" csnLow=");
Serial.println(limit[1],DEC);
if (!bottom_found) {
limit[k]--;
if (limit[k] == MINIMAL) {
bottom_found = true;
bottom_success = 0;
success = true;
}
} else {
bottom_success++;
}
}
}
Serial.print("Settle value found for ");
if (k == 0) {
Serial.print("csnHigh: ");
} else {
Serial.print("csnLow: ");
}
Serial.println(limit[k],DEC);
advice[k] = limit[k] + (limit[k] / 10);
limit[k] = 100;
}
Serial.print("Adviced Settle times are: csnHigh=");
Serial.print(advice[0],DEC);
Serial.print(" csnLow=");
Serial.println(advice[1],DEC);
while (true)
{
;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment