«Вечный» пульт управления на NRF24L01+

kobalt
Offline
Зарегистрирован: 12.08.2015

Имеется: приёмник и передатчик собранные на ардуино и NRF24L01+ (http://iarduino.ru/shop/Expansion-payments/nrf24l01-wireless-module-2-4g.html). Используется пленочная клавиатура типа (http://iarduino.ru/shop/Expansion-payments/elastichnaya-klaviatura-3x4-knopki.html) с библиотекой Keypad.

Все работает, но…

Передатчик потребляет много- батареек не напасешься.

Задача: сделать «вечный» пульт управления, который будет по нажатию на клавишу будить ардуину (у меня стоит Про мини 3,3), будить NRF24L01+, отправлять команду.

Затем в обратной последовательности засыпать (сразу или через какое то время – если пульт будет пользоваться).

Нашел примеры по усыплению ардуины и пробуждению по прерыванию. Не знаю только как получить сигнал со спящей клавиатуры. Можно ли с пленочной клавиатурой и с библиотекой Keypad использовать прерывания?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Можно, если перед сном поставить низкий уровень на пинах строк (или столбцов) и на других пинах (стоблцов или строк соответсвенно) поставить INPUT_PULLUP и разрешить по этим пинам прерывание типа PCINT. Вот по нему и будете просыпаться.

kobalt
Offline
Зарегистрирован: 12.08.2015

спасибо. буду рыть в этом направлении.

kobalt
Offline
Зарегистрирован: 12.08.2015
#include <Keypad.h>       // Подключаем библиотеку пленочной клавиатуры

const byte ROWS = 4; // 4 строки
const byte COLS = 3; // 3 столбца

byte keys[ROWS][COLS] = {
  {17,18,19},
  {14,15,16},
  {11,12,13},
  {20,21,22}
}; 

byte rowPins[ROWS] = {5, 6, 7, 8};   // на них подается 3,3В
byte colPins[COLS] = {4, 3, 14};     // на них поступает 3,3В при нажатии кнопки

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup() {
  Serial.begin(9600); //открываем порт для связи с ПК
}

void loop() {

 byte key = keypad.getKey();
  
  if (key){
    // Serial.println(key); // Передаем название нажатой клавиши в сериал порт
    Serial.print("Press key: "); Serial.println(key);
  }

}

 

kobalt
Offline
Зарегистрирован: 12.08.2015

Можно, если перед сном поставить низкий уровень на пинах строк (или столбцов) и на других пинах (стоблцов или строк соответсвенно) поставить INPUT_PULLUP

В loop()  перед сном  описать:

pinMode(3,INPUT_PULLUP);
pinMode(4,INPUT_PULLUP);
pinMode(14,INPUT_PULLUP);
​pinMode(5,INPUT_PULLUP);
pinMode(6,INPUT_PULLUP);
pinMode(7,INPUT_PULLUP);
​​pinMode(8,INPUT_PULLUP);

или это как то с помощью Keypad.h делается?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, сами-то чего-нибудь сделайте. Попробуйте, посмотрите, проверьте. Если это хобби, то от работы надо получать удовольствие, а какое удовольствие за каждой запятой на форум бегать?

kobalt
Offline
Зарегистрирован: 12.08.2015

)))

рою по чуть-чуть))

по добавленным строкам пока ошибок не выдается. теперь проверяю ноги на принадлежность к Группам PCINT. PCI0 у меня используется под NRF24L01+.  поэтой причине все пины клавиатуры надо перенести в PCI1 и PCI2 и "разрешить по этим пинам прерывание типа PCINT". как разрешить- пока не нарыл.

Green
Offline
Зарегистрирован: 01.10.2015

ЕвгенийП пишет:

Можно, если перед сном поставить низкий уровень на пинах строк (или столбцов) и на других пинах (стоблцов или строк соответсвенно) поставить INPUT_PULLUP и разрешить по этим пинам прерывание типа PCINT. Вот по нему и будете просыпаться.


Смотря как спать.) По idle экономии совсем не много(.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, спать надо максимально, чтобы только от PCINT проснуться. Другое дело, если это ардуина, а не голый МК, то вся эта сонливость - мастурбация одна.

Green
Offline
Зарегистрирован: 01.10.2015

Только 2, 3 и Res сможет создасть настоящую "вечность", иначе это будет порнография).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Green пишет:
Только 2, 3 и Res сможет создасть настоящую "вечность", иначе это будет порнография).

Похищал сердца у дам, видный парень Рамазан и теперь проблема вечна, ходят дамы безсердечны!!!

kobalt
Offline
Зарегистрирован: 12.08.2015

нашел пример решения с регистрами.

значения регистров PCMSK0 и PORTB,  PCMSK1 и PORTC,  PCMSK2 и PORTD должны быть одинаковыми?
kobalt
Offline
Зарегистрирован: 12.08.2015

ЕвгенийП пишет:

Можно, если перед сном поставить низкий уровень на пинах строк (или столбцов) и на других пинах (стоблцов или строк соответсвенно) поставить INPUT_PULLUP и разрешить по этим пинам прерывание типа PCINT. Вот по нему и будете просыпаться.

byte rowPins[ROWS] = {5, 6, 7, 14};   // на них подается 3,3В
byte colPins[COLS] = {4, 3, 2};       // на них поступает 3,3В при нажатии кнопки

можно ли на пины 5,6,7,14 ставить низкий уровень? как мы тогда что то получим на пинах 2,3,4?
разрешаем прерывания по всем 7 пинам или только для 2,3,4?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вопросы показывают. что Вы не поняли идеи. Посмотрите на схему матрицы и подумайте ещё

kobalt пишет:

можно ли на пины 5,6,7,14 ставить низкий уровень? как мы тогда что то получим на пинах 2,3,4?

Всё равно куда и какой уровень, лишь бы на строках он был один, а на столбцах другой. Ставьте каокй хотите и куда хотите.

kobalt пишет:

разрешаем прерывания по всем 7 пинам или только для 2,3,4?

По тем, что на INPUT, конечно.

kobalt
Offline
Зарегистрирован: 12.08.2015

#include <Keypad.h>       // Подключаем библиотеку пленочной клавиатуры

// клавиатура начало
const byte ROWS = 4; // 4 строки
const byte COLS = 3; // 3 столбца

byte keys[ROWS][COLS] = {
  {17,18,19},
  {14,15,16},
  {11,12,13},
  {20,21,22}
}; 

byte rowPins[ROWS] = {5, 6, 7, 14};   // на них подается 3,3В
byte colPins[COLS] = {4, 3, 2};       // на них поступает 3,3В при нажатии кнопки

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// клавиатура конец

void setup() {
  Serial.begin(9600); //открываем порт для связи с ПК

 // PORTB = 0b00111111;   // пины порта PB не задействованы
 // PORTC = 0b00000001;   // пины порта PC не задействованы
    PORTD = 0b00011100;     // используем пины 4,3,2  , пины 7,6,5, 1 и 0  не задействованы

// В нашей задаче разрешена группа  2. 
  PCICR = 0b00000100;

// разрешим прерывание на каждой линии, сделав запись в регистры PCMSK0...PCMSK2:
    PCMSK2 = 0b00011100;  // PCMSK2 - порт PORTD
}

void Test (byte key)  {
//byte key = keypad.getKey();
  
  if (key){
    // Передаем название нажатой клавиши в сериал порт
    Serial.print("Press key: "); Serial.println(key);
  }  
}


void loop() {

}
ISR(PCINT2_vect) {
    if (!(PIND & (1 << PD0))) {Test(0);/* Arduino pin 0 interrupt*/}
    if (!(PIND & (1 << PD1))) {Test(1);/* Arduino pin 1 interrupt*/}
    if (!(PIND & (1 << PD2))) {Test(2);/* Arduino pin 2 interrupt*/}
    if (!(PIND & (1 << PD3))) {Test(3);/* Arduino pin 3 interrupt*/}
    if (!(PIND & (1 << PD4))) {Test(4);/* Arduino pin 4 interrupt*/}
    if (!(PIND & (1 << PD5))) {Test(5);/* Arduino pin 5 interrupt*/}
    if (!(PIND & (1 << PD6))) {Test(6);/* Arduino pin 6 interrupt*/}
    if (!(PIND & (1 << PD7))) {Test(7);/* Arduino pin 7 interrupt*/}
}

вот такое чудо получилось)

при нажатии на кнопки клавиатуры иногда в порт сыпет 5, 6, 7, 1....

где я не прав?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не знаю, а что Вы сделали-то? Я Вам что писал в первом посте?

Я Вам писал делать это ПЕРЕД СНОМ чтобы проснуться. А при нормальной работе, всё выключаёте нахрен и пользуйтесь библиотекой как обычно. Это только чтобы проснуться техника. Понимаете? Проснулись - прерывания нафиг и спокойно живёте со своей библиотекой. Захотели спать - всё подготовили и тогда спим.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

Не знаю, а что Вы сделали-то? Я Вам что писал в первом посте?

Я Вам писал делать это ПЕРЕД СНОМ чтобы проснуться. А при нормальной работе, всё выключаёте нахрен и пользуйтесь библиотекой как обычно. Это только чтобы проснуться техника. Понимаете? Проснулись - прерывания нафиг и спокойно живёте со своей библиотекой. Захотели спать - всё подготовили и тогда спим.

Товарищ еще не озвучил на какой именно ардуине это реализует, вдруг на NANO? Для вачдога надо же сначала загрузчик перешить

kobalt
Offline
Зарегистрирован: 12.08.2015

kobalt пишет:

..... сделать «вечный» пульт управления, который будет по нажатию на клавишу будить ардуину (у меня стоит Про мини 3,3).......

это писал

 

kobalt
Offline
Зарегистрирован: 12.08.2015
#include <Keypad.h>       // Подключаем библиотеку пленочной клавиатуры

// клавиатура начало
const byte ROWS = 4; // 4 строки
const byte COLS = 3; // 3 столбца

byte keys[ROWS][COLS] = {
  {17,18,19},
  {14,15,16},
  {11,12,13},
  {20,21,22}
}; 

byte rowPins[ROWS] = {5, 6, 7, 14};   // на них подается 3,3В
byte colPins[COLS] = {4, 3, 2};       // на них поступает 3,3В при нажатии кнопки

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// клавиатура конец

void Zasipaem() {             //делаем это ПЕРЕД СНОМ чтобы проснуться
   // PORTB = 0b00111111;     // пины порта PB не задействованы
   // PORTC = 0b00000001;     // пины порта PC не задействованы
    PORTD = 0b00011100;       // используем пины 4,3,2  , пины 7,6,5, 1 и 0  не задействованы

// В нашей задаче разрешена группа  2. 
  PCICR = 0b00000100;

// разрешим прерывание на каждой линии, сделав запись в регистры PCMSK0...PCMSK2:
    PCMSK2 = 0b00011100;  // PCMSK2 - порт PORTD
  }

void Prosipaemsia() {
   PORTD = 0b00011100;     // используем пины 4,3,2  , пины 7,6,5, 1 и 0  не задействованы

// В нашей задаче разрешена группа  2. 
  PCICR = 0b00000100;

// запретим прерывание, работаем как обычно..
    PCMSK2 = 0b00000000;  // PCMSK2 - порт PORTD
  }
//

void setup() {
  Serial.begin(9600); //открываем порт для связи с ПК
}

void Test (byte key)  {
//byte key = keypad.getKey();
  
  if (key){
    // Передаем название нажатой клавиши в сериал порт
    //Serial.print("Press key: "); Serial.println(key);
    Serial.print("Pin: "); Serial.println(key);
  }  
}

void loop() {
  Zasipaem(); //засыпаем и ждем нажатия клавиш. при нажатии срабатывает прерывание.
}

ISR(PCINT2_vect) {
    if (!(PIND & (1 << PD0))) {  Prosipaemsia(); /* Arduino pin 0 interrupt*/}
    if (!(PIND & (1 << PD1))) {  Prosipaemsia(); /* Arduino pin 1 interrupt*/}
    if (!(PIND & (1 << PD2))) {  Prosipaemsia();  Test(2);/* Arduino pin 2 interrupt*/}
    if (!(PIND & (1 << PD3))) {  Prosipaemsia();  Test(3); /* Arduino pin 3 interrupt*/}
    if (!(PIND & (1 << PD4))) {  Prosipaemsia();  Test(4);/* Arduino pin 4 interrupt*/}
    if (!(PIND & (1 << PD5))) {  Prosipaemsia(); /* Arduino pin 5 interrupt*/}
    if (!(PIND & (1 << PD6))) {  Prosipaemsia(); /* Arduino pin 6 interrupt*/}
    if (!(PIND & (1 << PD7))) {  Prosipaemsia(); /* Arduino pin 7 interrupt*/}
}

не работает 

правильно я бужу ардуину?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не вижу, как Вы еёбудите по очень просто причине - Вы нигде её спать не укладываете.

Знаете, если у Вас именно ардуина, а не голый ичп, бросайте Вы это дело и забейте. Ничего Вы её сном не сэкономите. Там оснастка жрёт больше, чем сам МК.

kobalt
Offline
Зарегистрирован: 12.08.2015

ну почему же? у меня про мини с понижением частоты и программным усыпление без радиомодуля потребляет 0,17мА. меня устраивает. есть идея еще чуток уменьшить потребление, но пока не хочу ардуину "пилить". разберусь с просыпанием, займусь отключением радиомодуля (программно или отключением питания).

Green
Offline
Зарегистрирован: 01.10.2015

А должно быть 10 - 20 мка. С радиомодулем! Есть к чему стремиться.)

kobalt
Offline
Зарегистрирован: 12.08.2015

Green пишет:

А должно быть 10 - 20 мка. С радиомодулем! Есть к чему стремиться.)

а как такого добиться?

Green
Offline
Зарегистрирован: 01.10.2015

Известно как. Непосильным трудом.) Я намёк вам дал ранее.

kobalt
Offline
Зарегистрирован: 12.08.2015

Green пишет:
Только 2, 3 и Res сможет создасть настоящую "вечность"....

если Вы про это, то можно поподробнее?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016
void Zasipaem() {             //делаем это ПЕРЕД СНОМ чтобы проснуться
   // digitalSetup - LOW & PULL_UP
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
      digitalWrite(7,LOW);
      digitalWrite(14,LOW);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      pinMode(4, INPUT_PULLUP);