Im working on a wireless keyboard that currently works just fine.
Transmitter is an Attiny88 MHTINY Version connected to an rf24 module.
Receiver is a Arduino Micro with RF24.
Its all gravy except for the part where I try to incorporate low power(sleep) into the transmitter
(its running off a 2032 Cell Battery and currently dies within a few hrs.
I have already made the Attiny88 run on 1mhz / making all the pins that arnt being used in InputPULLUP to save power and im assuming going to (SLEEP) is the only way
ill be able to have it run for at least a week.
Here is the working code for the transmitter (without Low Power)
#include "SPI.h"
#include "RF24.h"
#include <Button.h>
// Radio, choose any pins on your micro-controller to use as the CE and CSN pins.
#define CE_PIN 9
#define CSN_PIN 10
const uint8_t ADDRESS[6] = "5n1p3";
// Maximum number of keys a shortcut can be, or max number of keys to send through the NRF24L01 per button.
// This needs to match with the receiver side.
const int MAX_SHORTCUT_KEYS = 4;
const int BTN_SHORTCUT_SIZE = (3 * MAX_SHORTCUT_KEYS) + (MAX_SHORTCUT_KEYS - 1) + 1;
struct ButtonInfo {
int btnPin;
char btnShortcut[BTN_SHORTCUT_SIZE];
};
// All keys are represented using their ASCII decimal/int value. This can be found here: www.asciitable.com
// First specify the pin number, then seperate each key for that button in a string by a space.
const ButtonInfo BUTTONS_INFO[] = {{A0, "130 226"},
{A1, "130 225"},
{A2, "130 234"},
{A3, "130 227"},
};
const int N_BUTTONS = sizeof(BUTTONS_INFO) / sizeof(BUTTONS_INFO[0]);
const uint16_t DEBOUNCE_MS = 10;
RF24 radio(CE_PIN, CSN_PIN);
Button *buttonObjs[N_BUTTONS];
void initRadio() {
if (!radio.begin()) {
while (1) {}
}
radio.setPALevel(RF24_PA_LOW);
radio.setPayloadSize(BTN_SHORTCUT_SIZE);
radio.openWritingPipe(ADDRESS);
radio.setDataRate(RF24_1MBPS);
radio.stopListening();
}
void initButtons() {
for(int i = 0; i < N_BUTTONS; i++) {
ButtonInfo btnInfo = BUTTONS_INFO[i];
buttonObjs[i] = new Button(btnInfo.btnPin, DEBOUNCE_MS);
buttonObjs[i] -> begin();
}
}
void setup() {
initRadio();
initButtons();
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);
pinMode(A6, INPUT_PULLUP);
pinMode(A7, INPUT_PULLUP);
pinMode(0, OUTPUT);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
}
void loop() {
// If any button pressed, then send the button keys through radio using the nRF24L01.
for(int i = 0; i < N_BUTTONS; i++) {
if(buttonObjs[i] -> pressed()) {
ButtonInfo btnInfo = BUTTONS_INFO[i];
radio.write(&btnInfo.btnShortcut, sizeof(btnInfo.btnShortcut));
break;
}
}
}
My problem is im trying to make it LOW POWER so that it can stay asleep and wake up and send the right code when I click one of the keyboard buttons. I pulled up the data sheet and looked up some examples from Nick Gammon and honestly Ive spent the whole last week learning as much as I can on Pin Change Interrupts because I cant use INT0 or INT1 as I am hoping to use the same buttons that I have configured already and they are PCINT Which from reading the datasheet I should be able to wake up from sleep. here is the Code with what I thought would be working code but it doesnt wake from sleep? Im not looking for a handout im just looking for some guidance because my brain is mushy from all the research. Here is the "non working Low power code"
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include "SPI.h"
#include "RF24.h"
#include <Button.h>
// Radio, choose any pins on your micro-controller to use as the CE and CSN pins.
#define CE_PIN 9
#define CSN_PIN 10
const uint8_t ADDRESS[6] = "5n1p3";
// Maximum number of keys a shortcut can be, or max number of keys to send through the NRF24L01 per button.
// This needs to match with the receiver side.
const int MAX_SHORTCUT_KEYS = 4;
const int BTN_SHORTCUT_SIZE = (3 * MAX_SHORTCUT_KEYS) + (MAX_SHORTCUT_KEYS - 1) + 1;
struct ButtonInfo {
int btnPin;
char btnShortcut[BTN_SHORTCUT_SIZE];
};
// All keys are represented using their ASCII decimal/int value. This can be found here: www.asciitable.com
// First specify the pin number, then seperate each key for that button in a string by a space.
const ButtonInfo BUTTONS_INFO[] = {{A0, "130 226"},
{A1, "130 225"},
{A2, "130 234"},
{A3, "130 227"},
};
const int N_BUTTONS = sizeof(BUTTONS_INFO) / sizeof(BUTTONS_INFO[0]);
const uint16_t DEBOUNCE_MS = 10;
RF24 radio(CE_PIN, CSN_PIN);
Button *buttonObjs[N_BUTTONS];
void initRadio() {
if (!radio.begin()) {
while (1) {}
}
radio.setPALevel(RF24_PA_LOW);
radio.setPayloadSize(BTN_SHORTCUT_SIZE);
radio.openWritingPipe(ADDRESS);
radio.setDataRate(RF24_1MBPS);
radio.stopListening();
}
void initButtons() {
for(int i = 0; i < N_BUTTONS; i++) {
ButtonInfo btnInfo = BUTTONS_INFO[i];
buttonObjs[i] = new Button(btnInfo.btnPin, DEBOUNCE_MS);
buttonObjs[i] -> begin();
}
}
void setup() {
initRadio();
initButtons();
pinMode(A0, INPUT);
digitalWrite(A0, HIGH);
pinMode(A1, INPUT);
digitalWrite(A1, HIGH);
pinMode(A2, INPUT);
digitalWrite(A2, HIGH);
pinMode(A3, INPUT);
digitalWrite(A3, HIGH);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);
pinMode(A6, INPUT_PULLUP);
pinMode(A7, INPUT_PULLUP);
pinMode(0, OUTPUT);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
}
void sleep() {
PCICR |= _BV(PCIE0);
PCICR |= _BV(PCIE1);
PCICR |= _BV(PCIE2);
PCICR |= _BV(PCIE3);// Enable Pin Change Interrupts
PCMSK1 |= _BV(PCINT8); // Use PC0 as interrupt pin
PCMSK1 |= _BV(PCINT9); // Use PC1 as interrupt pin
PCMSK1 |= _BV(PCINT10); // Use PC2 as interrupt pin
PCMSK1 |= _BV(PCINT11); // Use PC3 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement
sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
sei(); // Enable interrupts
sleep_cpu(); // sleep
cli(); // Disable interrupts
PCMSK1 &= ~_BV(PCINT8); // Turn off PC0 as interrupt pin
PCMSK1 &= ~_BV(PCINT9); // Turn off PC1 as interrupt pin
PCMSK1 &= ~_BV(PCINT10); // Turn off PC2 as interrupt pin
PCMSK1 &= ~_BV(PCINT11); // Turn off PC3 as interrupt pin
sleep_disable(); // Clear SE bit
ADCSRA |= _BV(ADEN); // ADC on
sei(); // Enable interrupts
} // sleep
ISR(PCINT0_vect) {
// This is called when the interrupt occurs, but I don't need to do anything in it
}
void loop() {
sleep();
// If any button pressed, then send the button keys through radio using the nRF24L01.
for(int i = 0; i < N_BUTTONS; i++) {
if(buttonObjs[i] -> pressed()) {
ButtonInfo btnInfo = BUTTONS_INFO[i];
radio.write(&btnInfo.btnShortcut, sizeof(btnInfo.btnShortcut));
break;
}
}
}
Thank you for taking the time to read this post and possibly help out.