toc спасибо! У вас ряд параметров в eeprom - так проще запускать индивидуальные устройства или вы предполагаете переконфигурирование по радио?
можно помучаю вопросами?
- channel подбирали или взяли какой понравился?
- PA_LEVEL он такой по умолчанию, а Data rate почему снизили? по факту я его тоже снизил)
- payload статический пока используете?
я вот думаю реально на связь должны влиять три вещи - канал, data rate и payloadsize
чтобы канал подобрать по идее надо делать скан и далее смотреть на результат radio.testRPD() чтобы выбрать лучший канал (точнее канал с минимальными конфликтами). Причем такую опрерацию неплохо бы делать время от времени, значит ее надо автоматизировать...
data rate по идее что 250кбит что 1 мбит для устройств умного дома не критично - обмениваться нужно совсем не большим объемом данных, а вот для устойчивости передачи это критично
ну и payload, по идее чем короче пакет, тем проще его передать без ошибок. Тут не хотелось бы себя ограничивать минимумом, наверно стоит использовать динамический размер - тогда часть сообщений можно посылать короткими, но если нужно, то можно отправить и длинные.
dimka спасибо. проверил скетч из 292 поста. все работает. а те кто ругают вас. я их не понимаю. предложили бы сами простой скетч с которым можно еще разобраться не из 50-100 строк.
к вам dimka вопрос: можете ли вы написать скетч беспроводного программатора для ардуины состоящий из:
преобразователь USB-232 далее ардуина далее NFR24l01
с другой стороны ардуина с NFR24l01 с которой уже програмируется другая ардуина
Если получится то потом заменить ардуину на самодельную на меге8. исходя из возможностей NFR24l01 меняем в файле boards скорость програмирования на более низкую (если понадобится)
если набросаете скетч готов сам все проверять в железе и дальнейшие разработки платы
jeka_tm, с удовольствием помогу.
Но пока сам запутался в трёх соснах.
Поэтому прошу помощи у вас.
jeka_tm, благодарю за поддержку, благородно, уважаю.
val_1 передаёт значение не больше 255,
а мне нужно передать, и принять 4146609271 .
что здесь нужно изменить ?
скетч sketch: передатчик и приёмник
передатчик
//передатчик
#include <SPI.h>
#include "RF24.h" // Подключаем скачанную библиотеку RF24.
//Контакты от радио модуля NRF24L01 подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
unsigned long pipe = 0xE8E8F0F0E1LL; // адрес канала передачи
unsigned long msg[1]; //переменная для отправки радио сигнала
void setup(void){
radio.begin();
radio.openWritingPipe(pipe); // Открываем канал передачи
//radio.setPayloadSize(9999999);
}
void loop() {
unsigned long val_1 = 255;
msg[0] = val_1,radio.write(msg, 1);
}
// val_1 передаёт значение не больше 255,
// а мне нужно передать, и принять 4146609271 .
// что здесь нужно изменить ?
приёмник
//приёмник
#include <SPI.h>
#include "RF24.h"
//Контакты от радио модуля NRF24L01+ подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
unsigned long pipe = 0xE8E8F0F0E1LL; // адрес канала
unsigned long msg[1]; //переменная для приёма радио сигнала
void setup()
{
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(1,pipe); // Открываем один из 6-ти каналов приема
radio.startListening(); // Начинаем слушать эфир
// radio.setPayloadSize(9999999);
}
void loop()
{
if (radio.available())radio.read(msg, 1);
Serial.println(msg[0]);
}
//передатчик
#include <SPI.h>
#include "RF24.h" // Подключаем скачанную библиотеку RF24.
//Контакты от радио модуля NRF24L01 подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9, 10);
unsigned long pipe = 0xE8E8F0F0E1LL; // адрес канала передачи
void setup()
{
radio.begin();
radio.openWritingPipe(pipe); // Открываем канал передачи
//radio.setPayloadSize(4);
}
void loop()
{
unsigned long val_1 = 4146609271;
radio.write(&val_1, 4);
delay(1000);
}
//приёмник
#include <SPI.h>
#include "RF24.h"
//Контакты от радио модуля NRF24L01+ подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
unsigned long pipe = 0xE8E8F0F0E1LL; // адрес канала
unsigned long msg = 0; //переменная для приёма радио сигнала
void setup()
{
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(1,pipe); // Открываем один из 6-ти каналов приема
radio.startListening(); // Начинаем слушать эфир
// radio.setPayloadSize(9999999);
}
void loop()
{
if(radio.available())
{
radio.read(&msg, 4);
Serial.println(msg);
}
}
может конечно глупость скажу. а может разделить на куски число по аналогии. только не по цифрам по 2 цифы например чтобы не было больше 255. а потом собрать в приемнике
byte chas_1 = chas/10; //1 цифра часов
byte chas_2 = chas%10; //2 цифра часов
я кстати не успокоился и решил проверить задержку. похоже где то в коде хороший косяк. отправленное число ни разу в том же виде не пришло. измеренное время соответствует или нет не понятно. но светодиоды rx и тх загораются почти одновременно
передача проходит не каждый раз
// Передатчик
#include <SPI.h>
#include "RF24.h"
byte UART[1]; // переменная для хранения полученного байта по UART
byte NRF24L01[1]; // переменная для хранения передаваемого байта через NRF24L01
unsigned long time1;
unsigned long time2;
unsigned long time;
//Контакты от радиомодуля NRF24L01 подключаем к пинамнам -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
const uint64_t pipe = 0xE8E8F0F0E1LL; // адрес канала передачи
void setup(void){
Serial.begin(9600); // задаем скорость UART
radio.begin(); //инициализируем NRF24L01
}
void loop(void){
//Ардуина к компу
if (Serial.available() > 0) { //если есть доступные данные по UART считываем байт
UART[1] = Serial.read();
time1 = micros();
radio.stopListening(); // обязательно вызывать перед write()
radio.openWritingPipe(pipe);
radio.write(UART, 1); //отправляем через NRF24L01
radio.startListening(); //включаем режзим чтения NRF24L01
}
if (radio.available()){ //проверяем если входные данные на NRF24L01
time2 = micros();
time = time2-time1;
bool done = false;
while (!done){
done = radio.read(NRF24L01, 1); //считываем байт
Serial.print(NRF24L01[1]);
Serial.print(" ");
Serial.println(time);
}
}
// Беспроводная ардуина
/* if (radio.available()){ //проверяем если входные данные на NRF24L01
bool done = false;
while (!done){
done = radio.read(NRF24L01, 1); //считываем байт
radio.stopListening(); // обязательно вызывать перед write()
radio.openWritingPipe(pipe);
radio.write(NRF24L01, 1); //отправляем через NRF24L01
radio.startListening();
}
}
*/
}
может конечно глупость скажу. а может разделить на куски число по аналогии. только не по цифрам по 2 цифы например чтобы не было больше 255. а потом собрать в приемнике
byte chas_1 = chas/10; //1 цифра часов
byte chas_2 = chas%10; //2 цифра часов
ничего личного, вы глупость написали) во первых нет необходимости расчленять переменную типа long на байты в программе - они и так фактически храняться как байты, но уровень абстрагирования языка С++ позволяет нам об этом думать реже
Во вторых в вашем коде вы пытаетесь разбить число по десятичной базе, если уж и разбивать на байты то по 8-ми битной базе типа так:
и опять понеслась реклама. пристрелите уже кто нибуть.
уже горячеее желание припаять этот чип тебе туда куда солнце не светит :) реально хочется вставить тебе паяльник включеный и не вынимать пока ты не собереш схему прошивки ПО РАДИО через PL2303 ( который просто узб-уарт преобразователь)
вот выкладываю рабочие sketch, передатчика и приёмника.
передатчик
//передатчик
#include <SPI.h>
#include "RF24.h" // Подключаем скачанную библиотеку RF24.
//Контакты от радио модуля NRF24L01 подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9, 10);
unsigned long pipe = 0xE8E8F0F0E1LL; // адрес канала передачи
unsigned long val_1 = 4146609299;
void setup()
{
radio.begin();
radio.openWritingPipe(pipe); // Открываем канал передачи
}
void loop()
{
radio.write(&val_1, 4);
delay(1000);
}
приёмник
//приёмник
#include <SPI.h>
#include "RF24.h"
//Контакты от радио модуля NRF24L01+ подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
unsigned long pipe = 0xE8E8F0F0E1LL; // адрес канала
unsigned long val_1;
void setup()
{
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(1,pipe); // Открываем один из 6-ти каналов приема
radio.startListening(); // Начинаем слушать эфир
}
void loop()
{
if (radio.available())radio.read(&val_1, 4);
Serial.println(val_1);
delay(1000);
}
и опять понеслась реклама. пристрелите уже кто нибуть.
уже горячеее желание припаять этот чип тебе туда куда солнце не светит :)
Ну чего вы? Где реклама? Ссылок нет. Дубликатов - нет. Код - начал сворачивать. Человек-то похоже, после пары намеков и пары вытертых постов понял что нужно вести себя скромнее.
Вообщем-то написал не "что-то оторванное от обсуждения", а как-бы "по теме". USB-конвертер привел как пример "авторесета". Ну вот понял он "что такое авторесет" - поделился. Ну не додумал что радиомодулем это не так просто реализовать как с PL2303. Ну так ведь и постил это уже не "урок от гуру", а уже как "обычный участник беседы". А "обычный" - и право на ошибку имеет :) Что же ему - теперь вообще ничего писать нельзя? Его, пока, никто не банил (хотя вам бы и хотелось ;) .
Как говорил Швейк: "если бы все были умными, то на свете было бы столько ума, что от этого каждый второй человек стал бы совершеннейшим идиотом"
P.S. Да, dimka, подпортили вы себе карму. Какое-то время, однозначно, к вам будет предвзятое отношение.
чтоб уместить в одном sketch использую /* */ для игнорирования компилятором второго sketch.
Где то я читал, существует волшебное слово, после него компилятор всё игнорирует.
Что это за волшебное слово ?
"Волшебное слово" называется "директивы препроцессора/условная компиляция".
Но, вы опять начинаете чесать левой пяткой правое ухо. Если у вас два скетча, так зачем их лепить в один файл? Если их два - сделайте два скетча.
И зачем валить все возникающие вопросы в одну тему? Вы название темы видите? Какое отношение имеет информация о том что у вас что-то получилось и вы что-то собираетесь к Nrf24l01+ ? Ну понятно, что вы сейчас над этим работаете, но ведь вопрос-то у вас про компиляцию, что он делает тут? В конце концов - все темы "про ардуину", так что нужно обсуждать все в одной ветке? У вас страх завести отдельную тему? В конечном итоге это выглядит как "вы на своей волне в чужой теме". Ну чисто как в анекдоте "Hа берегу сидят (М)ужики и ловят рыбу мимо проходит ёжик: Ёж: - Мужики, клей есть? М: - Hету. Через 40 минут. Ёжик: - Мужики, я вам клей принёс!"
v.01 Arduino сквозной радио удлинитель ИК пульта IR NRF24L01 RF wireless IR extender
код №1 для радио передатчика и ИК приёмника. ( transmitter )
/* код №1 для радио передатчика и ИК приёмника. ( transmitter )
****************************
урок от Дмитрия Осипова.
v.01 Arduino сквозной радио удлинитель ИК пульта IR NRF24L01 RF wireless IR extender
Version 0.1-2013/08/30
-----------------------------
изменения; в Version 0.1-2013
1.
2.
------------------------------
идеология;
На Arduino №1 устанавливаем ИК приёмник, и радио модуль NRF24L01+.
Нажимаем на кнопку своего ИК пульта, ИК приёмник на Arduino №1 принимает ИК сигнал, библиотека IRremote обрабатывает его и выдаёт код кнопки ИК пульта.
Далее отправляем этот код кнопки ИК пульта через радио модуль NRF24L01+ на Arduino №2.
На Arduino №2. радио модуль NRF24L01+, принимает код кнопки ИК пульта, библиотека IRremote обрабатывает его
и начинает слать ИК код кнопки пульта через ИК передатчик на конечное ИК устройство которым хотим управлять,
например через стены на большом расстоянии.
(прописывать в скетч sketch, ИК коды кнопок ВАШЕГО ИК пульта, не надо)
я прописал в sketch ИК протокол Panasonic, этот протокол используют и другие производители.
И ИК протокол JVC.
Техники от Других фирм с ИК у меня нет, поэтому добавить другие ИК протоколы, и протестировать нет возможности.
Для защиты от повторяющего цикла, рекомендую держать ИК передатчик от ИК приёмника на недосягаемом расстоянии друг от друга.
------------------------------------------
================================
что нам понадобиться.
Аппаратное:
1. ИК инфракрасный пульт.
2. Arduino -2 штуки.
3. Радио модуль NRF24L01+ 2.4GHz -2 штуки.
4. ИК инфракрасный приёмник - 1 штука. я использовал 38KHz
5. ИК инфракрасный передатчик - 1 штука. я использовал 38KHz
--------------------------------
программное:
2. Библиотеки.
1.IRremote, библиотека для работы с ИК сигналом.
Скачать библиотеку IRremote для ИК пульта
https://disk.yandex.ru/public/?hash=yNz1au3lm3/yyMHOYtnZ2UGSf19wTvYBZnkx...
IRremote эта библиотека кажется по новее будет
http://yadi.sk/d/0jIS1tfw6tbb7https://github.com/shirriff/Arduino-IRremote
2. RF24 библиотека для работы с радио модулем NRF24L01+ 2.4GHz
//https://github.com/maniacbug/RF24
//https://github.com/maniacbug/RF24/archive/master.zip
//http://yadi.sk/d/ZvMq19fB6lgPs
=======================================================
*/
//передатчик
#include <SPI.h>
#include "RF24.h" // Подключаем скачанную библиотеку RF24. для работы с радио модулем NRF24L01+
#include <IRremote.h> // подключаем скачанную библиотеку IRremote для работы с ИК сигналом.
int RECV_PIN = 4; //вход ИК приемника
IRrecv irrecv(RECV_PIN);
decode_results results;
//Контакты от радио модуля NRF24L01 подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9, 10);
int pipe = 0xE8E8F0F0E1LL; //адрес канала, для передачи радио сигнала.
void setup(){
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver // включить ИК приемник
radio.begin();
radio.openWritingPipe(pipe); // Открываем радио канал передачи
}
void loop()
{
// Еси пришел сигнал от ИК пульта, обрабатываем его с помощью библиотеки IRremote, то бишь получаем код кнопки ИК пульта.
// irrecv.decode(&results. Далее переходим к ожиданию следующего ИК сигнала irrecv.resume.
// Отправляем по радио через NRF24L01+ radio.write полученный код кнопки ИК пульта, который хранится в results.value.
// Перед отправкой конвертируем ИК код (& , 4).
if (irrecv.decode(&results))irrecv.resume(),radio.write(&results.value, 4);
// delay(1000);
// Serial.println(results.value);
// Serial.println(results.value, HEX);
// Serial.println(results.value, 4);
}
// благодарю за помощь при написание sketch, человеков под никами jeka_tm и maksim с http://arduino.ru/
код №2 для радио приёмника и ИК передатчика. ( receiver )
/* код №2 для радио приёмника и ИК передатчика. ( receiver )
****************************
урок от Дмитрия Осипова.
v.01 Arduino сквозной радио удлинитель ИК пульта IR NRF24L01 RF wireless IR extender
Version 0.1-2013/08/30
-----------------------------
изменения; в Version 0.1-2013
1.
2.
------------------------------
идеология;
На Arduino №1 устанавливаем ИК приёмник, и радио модуль NRF24L01+.
Нажимаем на кнопку своего ИК пульта, ИК приёмник на Arduino №1 принимает ИК сигнал, библиотека IRremote обрабатывает его и выдаёт код кнопки ИК пульта.
Далее отправляем этот код кнопки ИК пульта через радио модуль NRF24L01+ на Arduino №2.
На Arduino №2. радио модуль NRF24L01+, принимает код кнопки ИК пульта, библиотека IRremote обрабатывает его
и начинает слать ИК код кнопки пульта через ИК передатчик на конечное ИК устройство которым хотим управлять,
например через стены на большом расстоянии.
(прописывать в скетч sketch, ИК коды кнопок ВАШЕГО ИК пульта, не надо)
я прописал в sketch ИК протокол Panasonic, этот протокол используют и другие производители.
И ИК протокол JVC.
Техники от Других фирм с ИК у меня нет, поэтому добавить другие ИК протоколы, и протестировать нет возможности.
Для защиты от повторяющего цикла, рекомендую держать ИК передатчик от ИК приёмника на недосягаемом расстоянии друг от друга.
------------------------------------------
================================
что нам понадобиться.
Аппаратное:
1. ИК инфракрасный пульт.
2. Arduino -2 штуки.
3. Радио модуль NRF24L01+ 2.4GHz -2 штуки.
4. ИК инфракрасный приёмник - 1 штука. я использовал 38KHz
5. ИК инфракрасный передатчик - 1 штука. я использовал 38KHz
--------------------------------
программное:
2. Библиотеки.
1.IRremote, библиотека для работы с ИК сигналом.
Скачать библиотеку IRremote для ИК пульта
https://disk.yandex.ru/public/?hash=yNz1au3lm3/yyMHOYtnZ2UGSf19wTvYBZnkx...
IRremote эта библиотека кажется по новее будет
http://yadi.sk/d/0jIS1tfw6tbb7https://github.com/shirriff/Arduino-IRremote
2. RF24 библиотека для работы с радио модулем NRF24L01+ 2.4GHz
//https://github.com/maniacbug/RF24
//https://github.com/maniacbug/RF24/archive/master.zip
//http://yadi.sk/d/ZvMq19fB6lgPs
=======================================================
*/
//приёмник
#include <SPI.h>
#include "RF24.h" // Подключаем скачанную библиотеку RF24. для работы с радио модулем NRF24L01+
#include <IRremote.h> // подключаем скачанную библиотеку IRremote для работы с ИК сигналом.
// ВАЖНО !!! (PIN 3;) выход ИК передатчика ((PIN 3;)на другой PIN изменить нельзя)
// define PanasonicAddress хранит протокол ИК сигнала Panasonic
// этот протокол используют и другие производители
// можно порыться в библиотеке IRremote, и добавить другие протоколы.
// устал я для начала пойдёт и так
// ой вспомнил у меня старая камера с ИК JVC есть, сейчас и для техники JVC добавлю протокол.
// Других фирм с ИК у меня нет, поэтому добавить другие ИК протоколы и протестировать нет возможности.
#define PanasonicAddress 0x4004 // Panasonic address (Pre data)
IRsend irsend;
unsigned long IR_Button; // сюда сохраним ИК код полученный по радио
//Контакты от радио модуля NRF24L01+ подключаем к pins -> Arduino
//SCK -> 13//MISO -> 12//MOSI -> 11//CSN -> 10//CE -> 9
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
int pipe = 0xE8E8F0F0E1LL; // адрес радио канала
void setup()
{
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(1,pipe); // Открываем один из 6-ти каналов приема
radio.startListening(); // Начинаем слушать эфир
}
void loop()
{
// while radio.available()) (если - пока) поступили данные с радио модуля,читаем их radio.read, и сохраняем их в IR_Button,
// предварительно раз конвертировать & , 4 . То бишь в IR_Button сохранится пришедший ИК код кнопки пульта.
// Далее отправляем через ИК передатчик irsend. на конечное устройство.Сначала шлём ИК протокол Panasonic
//sendPanasonic(PanasonicAddress, за ним подставляем код кнопки, IR_Button.
// Тоже самое только протокол JVC, sendJVC.
IR_Button=0; // опустошаем IR_Button
while (radio.available())
radio.read(&IR_Button, 4),
irsend.sendPanasonic(PanasonicAddress,IR_Button),
irsend.sendJVC(IR_Button, 16,0);
// delay(1000);
// Serial.println(IR_Button);
// Serial.println(IR_Button,HEX);
// Serial.println(PanasonicAddress);
// Serial.println(PanasonicAddress,IR_Button);
// Serial.println(PanasonicAddress,(IR_Button,HEX));
}
// благодарю за помощь при написание sketch, человеков под никами jeka_tm и maksim с http://arduino.ru/
toc спасибо! У вас ряд параметров в eeprom - так проще запускать индивидуальные устройства или вы предполагаете переконфигурирование по радио?
можно помучаю вопросами?
- channel подбирали или взяли какой понравился?
- PA_LEVEL он такой по умолчанию, а Data rate почему снизили? по факту я его тоже снизил)
- payload статический пока используете?
я вот думаю реально на связь должны влиять три вещи - канал, data rate и payloadsize
чтобы канал подобрать по идее надо делать скан и далее смотреть на результат radio.testRPD() чтобы выбрать лучший канал (точнее канал с минимальными конфликтами). Причем такую опрерацию неплохо бы делать время от времени, значит ее надо автоматизировать...
data rate по идее что 250кбит что 1 мбит для устройств умного дома не критично - обмениваться нужно совсем не большим объемом данных, а вот для устойчивости передачи это критично
ну и payload, по идее чем короче пакет, тем проще его передать без ошибок. Тут не хотелось бы себя ограничивать минимумом, наверно стоит использовать динамический размер - тогда часть сообщений можно посылать короткими, но если нужно, то можно отправить и длинные.
Устройств у меня будет 2-3. Пока community сообщество не написало бутлойдер для nrf24l01+ хочется иметь возможность хоть что-то менять удалённо, поэтому в eeprom.
Канал - сканнером посмотрел, и выбрал первый более менее свободный. Уже не помню номер.
Скорость понизил потому, что в даташите написано, что так надёжнее связь. Но потребление энергии выше.
Размер полезной нагрузки буду использовать фиксированный, ибо aes128.
по умолчанию другой: RF24_PA_MAX - задаётся в begin. И для меня это новость.
что за библиотека? у maniacbug нет такого, а есть вот что:
Цитата:
Relative mnemonics have been used to allow for future PA level changes. According to 6.5 of the nRF24L01+ specification sheet, they translate to: RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, and RF24_PA_HIGH=0dBm.
я проверял на ардуине через getPALevel - возвращается по умолчанию именно RF24_PA_HIGH
по умолчанию другой: RF24_PA_MAX - задаётся в begin. И для меня это новость.
что за библиотека? у maniacbug нет такого, а есть вот что:
Цитата:
Relative mnemonics have been used to allow for future PA level changes. According to 6.5 of the nRF24L01+ specification sheet, they translate to: RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, and RF24_PA_HIGH=0dBm.
я проверял на ардуине через getPALevel - возвращается по умолчанию именно RF24_PA_HIGH
А RF24_PA_HIGH выдает потому как вот здесь он не менял ничего )
Но смысл не изменился конечно же. Однако, устанавливать, как я понимаю, нужно именно RF24_PA_MAX. Поправьте, если не прав.
P.S. Очень разочарован дальностью данных модулей. При тех же тестовых скетчах helloworld_rx и helloworld_tx не всегда "пробивает" стену из газосиликатных блоков и кирпича (в полкирпича) на расстоянии около 5м. Даже при условии radio.setDataRate(RF24_250KBPS) (хотя так и намного лучше).
большое спасибо за ссылку. доходчиво написано, но не сразу все понятно. я правильно понял этот код?
unsigned long val = 99999; //создаем переменную длиной 4 байта со значением 99999
unsigned char* abyte = (unsigned char*)&val; //указателю abyte на переменную типа unsigneв char присваиваем адрес переменной val
unsigned char byte0 = abyte[0]; //так как размер больше 1 байта образуется что то вроде массива
unsigned char byte1 = abyte[1]; //с элементами размером 1байт, где можно считать отдельные элементы
unsigned char byte2 = abyte[2]; //в сумме все 4 байта образуют число 99999
unsigned char byte3 = abyte[3]; //здесь считываем соответственно 4 байт
непонятно почему именно unsigned char если val unsigned long?
сам по себе адрес переменной одинаковая сущность вне зависимости от того на какую переменную он ссылается - все потому, что адрес указывает на первый байт в памяти вне зависимости от того сколько там этих байт
разница возникает когда вы обращаетесь к данным используя адрес. В строке присвоения:
byte byte0 = abyte[0];
если ваш abyte является ссылкой на тип byte, то при присвоении байт присваевается байту без каких-то преобразований - из памяти берется один байт и присваевается переменной byte0
А вот если вы определили abyte как ссылку на long, то в строке присвоения на самом деле компилятор сначала возьмет по адресу не один байт, а целых четыре! (длина long в ардуино), после этого из этих четырех байт попробует сделать переменную типа byte
Какие могут быть проблемы? Во превых не рекомендуется в лоб преобразовывать более длинный тип данных в более короткий (long в byte) не понимая с какими данными мы имеем дело. Могут быть нюансы преобразования и результат будет отличаться от ожидаемого.
Но это еще полбеды. В строке:
byte byte3 = abyte[3];
вы обращаетесь к "чужой" памяти! Ведь изначально long в памяти занимает 4 байта, обращаясь к третьему элементу массива вы прибавляете к адресу первого байта еще 3 - таким образом вы адресуете последний байт данных, но! так как ваша переменная типа (unsigned long*) вы берете не один байт, а целых четыре - тем самым вылезаете в "чужую" память на 3 байта. Последствия этого непредсказуемы, от некорректной работы скетча до его полного зависания. Так делать нельзя
вы обращаетесь к "чужой" памяти! Ведь изначально long в памяти занимает 4 байта, обращаясь к третьему элементу массива вы прибавляете к адресу первого байта еще 3 - таким образом вы адресуете последний байт данных, но! так как ваша переменная типа (unsigned long*) вы берете не один байт, а целых четыре - тем самым вылезаете в "чужую" память на 3 байта. Последствия этого непредсказуемы, от некорректной работы скетча до его полного зависания. Так делать нельзя
Все еще хуже: определив abyte, как массив элементов unsigned long, при обращении к четвертому элементу массива (abyte[3] - это четвертый элемент массива, а не третий: не забываем, что индексация начинается с нуля!) вы обратитесь к области памяти, лежащей не на 3, а на 9-12 байтов дальше той области, в которой хранится искомая переменная, то есть далеко-далеко от той области памяти, которую мы намеревались исследовать побайтно. Почему? Потому, что при адресации элементов массивов используется не обычная арифметика, а арифметика указателей. Грубо - при увеличении индекса массива на единицу указатель смещается на длину типа данных, хранящихся в массиве (в нашем случае - на 4). Первый (с индексом 0) элемент массива покрывает исследуемую переменную, второй - оккупирует 4 байта сразу вслед за этой переменной (то есть занимает 1-й, 2-й, 3-й и 4-й байты вслед за исследуемой переменной), третий лежит на 5 байтов дальше последнего байта исследуемой переменной, и так далее...
мда. спасибо. совсем запутался. как то это сложно)
Да чего тут сложного-то:
представьте память в виде длинной книжной полки, а переменные - как собрания сочинений. Байты - совсем неплодовитые писатели (по одной книжечке), целые - двухтомники, длинные целые - четырехтомники, и так далее. Строки - ну это ваще полные собрания сочинений.
Байтовый массив - участок полки от n-й книжки до m-й...
Массив с длинными целыми - место, где подряд стоит несколько четырехтомников. Но как вы понимаете, такой участок полки можно и как байтовый массив рассматривать - просто число элементовы вырастет в четыре раза, например, вместо десяти четырехтомников вы уже будете видеть перед собой сорок отдельных томиков.
Или в рамках вашей задачи - стоит на полке четырехтомник писателя "val". Вы можете снять этот четырехтомник целиком, обратившись к переменной val. Но также можете дергать и по книжечке - всего-то необходимо проинструктировать библиотекаря, по сколько книг приносить (unsigned char) и куда лесенку приставить (... abyte = ...&val).
а можем мы эти байты менять? например 3 байт хочу чтобы был FF, значение long соответственно изменится
Разрешаю...
Измените - доложите о результатах.
попытаюсь.
не до конца все равно понял запись
unsigned char* abyte = (unsigned char*)&val;
указатель abyte на переменную типа unsigned char = (ссылка на переменную типа unsigned char)адрес val
это правильно? после = не догоняю. указатель abyte равен адресу val. зачем перед этим в скобках указатель на переменную типа unsigned char?
блин как то мне реально тяжело дается. сделать чертеж и схему на шкаф с кучей оборудования серваками, упсами, преобразователями интерфейсов, внутренней разводкой и тп легко. а тут чувствую себя ребенком который учится читать)))) похоже надо какую нибудь книжку почитать может пойму
IMHO тут использование синтаксиса массивов - только запустывает. Это уже как раз "вывихи мозгов", нужно еще понимать что "массив это на самом деле указатель".
Так что я бы, раз пошли по пути указателей, то использовал бы оператор разименования указателя.
n = *pn; // Присвоить n то значение , на которое указывает pn.
А еще, раз мы говорим "байты", то имеет смысл использовать именно "ардуино терминологию". Есть же специальный тип byte . Это синоним unsigned char, в арунине, только писать короче.
void setup(){
Serial.begin(9600);
unsigned long val = 0xAABBCCDD; // оно как-то виднее так где какой байт
unsigned long* p_val=&val; // поместили адресс val в указатель на long, сам адресс - это "длинное число".
Serial.print("p_val="); Serial.println( (unsigned long)p_val,DEC); // привели его к unsigned long - что бы вывести именно адресс, а не содрежимое куда он указвает
byte* pbyte_0=(byte*)p_val; // взяли адрес из p_val поместили его в переменную типа "указатель на байт".
// считайте что у вас как-бы два "дорожных указателя". Один говорит "через 300 метров будет щебенка длиной 4 км.,
// а второй говорит через 300 метров будет отбойник длинной 1 км.
// они указывает на "разные вещи", но на один и тот же адресс - "через 300 метров".
// в результате - у нас в pbyte_0 лежит адресс памяти где val начинается. его первый байт.
byte* pbyte_1=pbyte_0+1; // pbyte_1 указывает на следующий байт в памяти. увеличили мы не значение, а именно "адресс"
byte* pbyte_2=pbyte_1+1; // или можно было =pbyte_0+2;
byte* pbyte_3=pbyte_2+1; // можно было =pbyte_0+3;
// выводим именно адреса указателей, чисто посмотреть как они выглядят.
Serial.println();
Serial.println("pbyte_XXXX");
Serial.println( (unsigned long)pbyte_0); // будет то же число что мы выводили и для p_val
Serial.println( (unsigned long)pbyte_1);
Serial.println( (unsigned long)pbyte_2);
Serial.println( (unsigned long)pbyte_3);
Serial.println();
// а теперь берем значения куда указывает указатели.
byte byte_0=*pbyte_0;
byte byte_1=*pbyte_1;
byte byte_2=*pbyte_2;
byte byte_3=*pbyte_3;
// и выводим их как HEX, как и оригинальное число задавали
Serial.println();// визуальная отбивочка
Serial.println("byte_XXX");
Serial.println(byte_0,HEX);
Serial.println(byte_1,HEX);
Serial.println(byte_2,HEX);
Serial.println(byte_3,HEX);
// а теперь все то же самое, толкьо циклом и используя всего один указатель
Serial.println();// визуальная отбивочка
Serial.println("byte_XXX in 'for' with pointers");
byte* p=(byte*)&val; // делаем указатель на val
for(byte i=0;i<4;i++){
Serial.print(*p,HEX); // сразу выводим значение куда указывает указатель. так как сам указатель "типа байт" - выведется только байт
Serial.print(i==3?"\n":","); // для красоты вывода
p++;// сдвигаем указатель на одну ячеку
}
// и один варант. только сам указатель менять не будет
Serial.println();// визуальная отбивочка
Serial.println("byte_XXX in 'for' with pointers2");
p=(byte*)&val; // возвращаем что-бы указатель опят на начало val указывал.
for(byte i=0;i<4;i++){
Serial.print(*(p+i),HEX);
Serial.print(i==3?"\n":","); // для красоты вывода
}
// и еще один вариант, вообще без введения дополнительного указателя, каждый раз будем брать адрес val
Serial.println();// визуальная отбивочка
Serial.println("byte_XXX in 'for' without pointers");
for(byte i=0;i<4;i++){
Serial.print(* ( (byte*)&val+i ),HEX);
Serial.print(i==3?"\n":","); // для красоты вывода
}
}
void loop(){
}
Выводит:
p_val=8682
pbyte_XXXX
8682
8683
8684
8685
byte_XXX
DD
CC
BB
AA
byte_XXX in 'for' with pointers
DD,CC,BB,AA
byte_XXX in 'for' with pointers2
DD,CC,BB,AA
byte_XXX in 'for' without pointers
DD,CC,BB,AA
указатель abyte на переменную типа unsigned char = (ссылка на переменную типа unsigned char)адрес val
это правильно? после = не догоняю. указатель abyte равен адресу val. зачем перед этим в скобках указатель на переменную типа unsigned char?
Все правильно. Просто когда мы написали &val компилятор рассуждает примерно так.
1. Вижу &val, так как val у нас типа "unsigned long" значит это выражение возвращает "unsigned long *"
2. Но, его пытаются присвоить переменной типа "unsigned char*" - наверное это ошибка.
Когда же мы написали (unsigned char*)&val; мы сказали компилятору "вот то что вернут &val - считай типом "unsigned char*". Твое мнение по поводу того что вернул нам &val - нас не интересует.
В результате мы взяли только информацию об адресе, но забили на информацию о типе объекта куда указывал указатель.
Вообщем - компилятор пытается нас предостеречь от ошибки, а явным указанием типа мы говорим "спокуха, мы знаем что делаем".
"По умному" эта операция называется Приведение типа — Википедия . Когда у нас есть выражение одного типа, а нам нужно преобразовать его в другой тип.
leshak спасибо большое за ответы и что не стал пинать неразбирающегося. большую часть уже понял, попозже еще раз перечитаю чтобы лучше уложилось в голове. за большое количество коментариев отдельное спасибо. так намного яснее
если уже пошел разговор о разбивке числа на байты(правильно ли здесь называть разбивкой? мы же не разбиваем а просто копируем отдельные байты) возникает вопрос. например нам нужно передать через nRF24L01 2 байта: 1 байт например для одного шима (у шима как раз удобно максимум 255) и 1 байт для второго. nRF24L01 передает за раз максимум один байт (возможно я ошибаюсь, было где то написано на форуме). но есть возможность передать 2 байта
radio.write(&val_1, 2);
radio.read(msg, 2);
как разбить число на байты уже понятно. а как 2 отдельных байта собрать в один, то есть не суммирую а поставив их рядом чтобы потом разбить. есть конечно более простой путь:
отправить сначала число, соответствующее 1 шиму(сами задаем число для условия). приемник будет знать что сейчас придет следующим байт первого шима. отправляем значение 1 шима. зачем число 2 шима, отправляем значение 2 шима
ну и по кругу.
первый вариант наверно все таки правильнее. в принятом числе первый байт всегда 1 шим, 2 байт всегда 2 шим
я пробовал подобным образом. не получилось. только одно значение 1 отправлялось. значит у меня какая то ошибка была. спасибо. попробую с помощью вашего кода
блин дошло почему. я забыл тогда указать цифру 2 (то что 2 байта отправлять), было один. и ожидал еще увидеть 2 байт)))
Ничего библиотека не собирает, а даже наоборот - разбивает, по одному байту, для того что бы поочередно помещать эти байты в регистр данных SPI и отправить в nRF24L01. А nRF24L01 массив до 32 байт всегда отправляется одним пакетом.
Ничего библиотека не собирает, а даже наоборот - разбивает, по одному байту, для того что бы поочередно помещать эти байты в регистр данных SPI и отправить в nRF24L01. А nRF24L01 массив до 32 байт всегда отправляется одним пакетом.
то есть nRF24L01 всегда отправляет 32 байта даже если все 32 байта не используют? это я так из интереса спрашиваю
Есть два режима работы - фиксированная длина пакета и динамическая
в первом случае во время инициализации чипа вы указываете размер пакета и любая отправка по радио будет иметь эту длинну, но не обязательно 32 байта. Если вы хотите отправлять не более одного байта - можету указать один байт
в динамическом режиме каждый пакет может иметь свою длину
вы в setup что-то кроме begin() и setPayloadSize() настраиваете?
toc спасибо! У вас ряд параметров в eeprom - так проще запускать индивидуальные устройства или вы предполагаете переконфигурирование по радио?
можно помучаю вопросами?
- channel подбирали или взяли какой понравился?
- PA_LEVEL он такой по умолчанию, а Data rate почему снизили? по факту я его тоже снизил)
- payload статический пока используете?
я вот думаю реально на связь должны влиять три вещи - канал, data rate и payloadsize
чтобы канал подобрать по идее надо делать скан и далее смотреть на результат radio.testRPD() чтобы выбрать лучший канал (точнее канал с минимальными конфликтами). Причем такую опрерацию неплохо бы делать время от времени, значит ее надо автоматизировать...
data rate по идее что 250кбит что 1 мбит для устройств умного дома не критично - обмениваться нужно совсем не большим объемом данных, а вот для устойчивости передачи это критично
ну и payload, по идее чем короче пакет, тем проще его передать без ошибок. Тут не хотелось бы себя ограничивать минимумом, наверно стоит использовать динамический размер - тогда часть сообщений можно посылать короткими, но если нужно, то можно отправить и длинные.
dimka спасибо. проверил скетч из 292 поста. все работает. а те кто ругают вас. я их не понимаю. предложили бы сами простой скетч с которым можно еще разобраться не из 50-100 строк.
к вам dimka вопрос: можете ли вы написать скетч беспроводного программатора для ардуины состоящий из:
преобразователь USB-232 далее ардуина далее NFR24l01
с другой стороны ардуина с NFR24l01 с которой уже програмируется другая ардуина
Если получится то потом заменить ардуину на самодельную на меге8. исходя из возможностей NFR24l01 меняем в файле boards скорость програмирования на более низкую (если понадобится)
если набросаете скетч готов сам все проверять в железе и дальнейшие разработки платы
может конечно глупость скажу. а может разделить на куски число по аналогии. только не по цифрам по 2 цифы например чтобы не было больше 255. а потом собрать в приемнике
я кстати не успокоился и решил проверить задержку. похоже где то в коде хороший косяк. отправленное число ни разу в том же виде не пришло. измеренное время соответствует или нет не понятно. но светодиоды rx и тх загораются почти одновременно
передача проходит не каждый раз
время по разному. от 2000 до 30000 мкс
беспроводной UART можно сделать по аналогии с LC-1000U фирмы Inhaos
http://www.inhaos.com/uploadfile/otherpic/UM-LC-1000U-V10-EN.pdf
может конечно глупость скажу. а может разделить на куски число по аналогии. только не по цифрам по 2 цифы например чтобы не было больше 255. а потом собрать в приемнике
ничего личного, вы глупость написали) во первых нет необходимости расчленять переменную типа long на байты в программе - они и так фактически храняться как байты, но уровень абстрагирования языка С++ позволяет нам об этом думать реже
Во вторых в вашем коде вы пытаетесь разбить число по десятичной базе, если уж и разбивать на байты то по 8-ми битной базе типа так:
или так, будет привязано к архитектуре зато компактнее:
я идею предлагал и сразу написал может глупость. а как она реализуется точно не знал как разбить на 8 бит
есть одна проблема. там нет DTR вывода. поэтому придется вручную делать резет, что неудобно. хотелось бы все таки полноценный переходник
и опять понеслась реклама. пристрелите уже кто нибуть.
уже горячеее желание припаять этот чип тебе туда куда солнце не светит :) реально хочется вставить тебе паяльник включеный и не вынимать пока ты не собереш схему прошивки ПО РАДИО через PL2303 ( который просто узб-уарт преобразователь)
приёмник
и опять понеслась реклама. пристрелите уже кто нибуть.
уже горячеее желание припаять этот чип тебе туда куда солнце не светит :)
Ну чего вы? Где реклама? Ссылок нет. Дубликатов - нет. Код - начал сворачивать. Человек-то похоже, после пары намеков и пары вытертых постов понял что нужно вести себя скромнее.
Вообщем-то написал не "что-то оторванное от обсуждения", а как-бы "по теме". USB-конвертер привел как пример "авторесета". Ну вот понял он "что такое авторесет" - поделился. Ну не додумал что радиомодулем это не так просто реализовать как с PL2303. Ну так ведь и постил это уже не "урок от гуру", а уже как "обычный участник беседы". А "обычный" - и право на ошибку имеет :) Что же ему - теперь вообще ничего писать нельзя? Его, пока, никто не банил (хотя вам бы и хотелось ;) .
Как говорил Швейк: "если бы все были умными, то на свете было бы столько ума, что от этого каждый второй человек стал бы совершеннейшим идиотом"
P.S. Да, dimka, подпортили вы себе карму. Какое-то время, однозначно, к вам будет предвзятое отношение.
чтоб уместить в одном sketch использую /* */ для игнорирования компилятором второго sketch.
"Волшебное слово" называется "директивы препроцессора/условная компиляция".
Но, вы опять начинаете чесать левой пяткой правое ухо. Если у вас два скетча, так зачем их лепить в один файл? Если их два - сделайте два скетча.
И зачем валить все возникающие вопросы в одну тему? Вы название темы видите? Какое отношение имеет информация о том что у вас что-то получилось и вы что-то собираетесь к Nrf24l01+ ? Ну понятно, что вы сейчас над этим работаете, но ведь вопрос-то у вас про компиляцию, что он делает тут? В конце концов - все темы "про ардуину", так что нужно обсуждать все в одной ветке? У вас страх завести отдельную тему? В конечном итоге это выглядит как "вы на своей волне в чужой теме". Ну чисто как в анекдоте "Hа берегу сидят (М)ужики и ловят рыбу мимо проходит ёжик: Ёж: - Мужики, клей есть? М: - Hету. Через 40 минут. Ёжик: - Мужики, я вам клей принёс!"
на это:
полуофф - на dx появился модуль с усилителем по хорошей цене http://dx.com/p/e01-ml01dp3-long-distance-nrf24l01p-pa-lna-wireless-tran...
v.01 Arduino сквозной радио удлинитель ИК пульта IR NRF24L01 RF wireless IR extender
код №1 для радио передатчика и ИК приёмника. ( transmitter )
код №2 для радио приёмника и ИК передатчика. ( receiver )
v.01 Arduino сквозной радио удлинитель ИК пульта IR NRF24L01 RF wireless IR extender
6 баксов с бесплатной пересылкой
http://www.aliexpress.com/item/IR-Extender-Infrared-Repeater-Remote-Control-2-Emitter-1-Receiver-USB-Adatper/1092747597.html
toc спасибо! У вас ряд параметров в eeprom - так проще запускать индивидуальные устройства или вы предполагаете переконфигурирование по радио?
можно помучаю вопросами?
- channel подбирали или взяли какой понравился?
- PA_LEVEL он такой по умолчанию, а Data rate почему снизили? по факту я его тоже снизил)
- payload статический пока используете?
я вот думаю реально на связь должны влиять три вещи - канал, data rate и payloadsize
чтобы канал подобрать по идее надо делать скан и далее смотреть на результат radio.testRPD() чтобы выбрать лучший канал (точнее канал с минимальными конфликтами). Причем такую опрерацию неплохо бы делать время от времени, значит ее надо автоматизировать...
data rate по идее что 250кбит что 1 мбит для устройств умного дома не критично - обмениваться нужно совсем не большим объемом данных, а вот для устойчивости передачи это критично
ну и payload, по идее чем короче пакет, тем проще его передать без ошибок. Тут не хотелось бы себя ограничивать минимумом, наверно стоит использовать динамический размер - тогда часть сообщений можно посылать короткими, но если нужно, то можно отправить и длинные.
Устройств у меня будет 2-3. Пока
communityсообщество не написало бутлойдер для nrf24l01+ хочется иметь возможность хоть что-то менять удалённо, поэтому в eeprom.Канал - сканнером посмотрел, и выбрал первый более менее свободный. Уже не помню номер.
Скорость понизил потому, что в даташите написано, что так надёжнее связь. Но потребление энергии выше.
Размер полезной нагрузки буду использовать фиксированный, ибо aes128.
testRDP себе добавлю. спасибо за идею.
Размер полезной нагрузки буду использовать фиксированный, ибо aes128.
что за сканер каналов?
поделитесь опытом про aes128, как сделали?
Размер полезной нагрузки буду использовать фиксированный, ибо aes128.
что за сканер каналов?
поделитесь опытом про aes128, как сделали?
scanner - пример в RF24.
aes - https://github.com/DavyLandman/AESLib
2 бакса с бесплатной пересылкой, радиоканал 433 Мгц, безпроводной.
Взял парочку, в комплекте вроде-бы 2 блока питания 5 Вольт 1 Ампер. Пригодятся куда-нибудь.
http://www.ebay.com/itm/Wireless-IR-Remote-Extender-Repeater-Infrared-Tr...
- PA_LEVEL он такой по умолчанию
по умолчанию другой: RF24_PA_MAX - задаётся в begin. И для меня это новость.
по умолчанию другой: RF24_PA_MAX - задаётся в begin. И для меня это новость.
что за библиотека? у maniacbug нет такого, а есть вот что:
я проверял на ардуине через getPALevel - возвращается по умолчанию именно RF24_PA_HIGH
по умолчанию другой: RF24_PA_MAX - задаётся в begin. И для меня это новость.
что за библиотека? у maniacbug нет такого, а есть вот что:
я проверял на ардуине через getPALevel - возвращается по умолчанию именно RF24_PA_HIGH
Очевидно, вот здесь.
Насколько я понимаю, это и есть maniacbug библиотека.
Начиная с 796-й строки устанавливается уровень (setPALevel). Есть там и RF24_PA_MAX и RF24_PA_HIGH.
Правда и комментарий: switch uses RAM (evil!). Где он там рам использует? Или я что-то недопонял?
Посмотрел исходник, похоже он поменял названия и high стал max, но суть не изменилась, зато mid исчез) видимо с названием max дальше бьет)
А RF24_PA_HIGH выдает потому как вот здесь он не менял ничего )
Но смысл не изменился конечно же. Однако, устанавливать, как я понимаю, нужно именно RF24_PA_MAX. Поправьте, если не прав.
P.S. Очень разочарован дальностью данных модулей. При тех же тестовых скетчах helloworld_rx и helloworld_tx не всегда "пробивает" стену из газосиликатных блоков и кирпича (в полкирпича) на расстоянии около 5м. Даже при условии radio.setDataRate(RF24_250KBPS) (хотя так и намного лучше).
диапазон не очень удачный у модулей, в городе из за wifi с обстановкой совсем труба
тем и хороша mesh или полу-mesh сеть
Во вторых в вашем коде вы пытаетесь разбить число по десятичной базе, если уж и разбивать на байты то по 8-ми битной базе типа так:
или так, будет привязано к архитектуре зато компактнее:
axill можете поподробнее объяснить как тут разбивается на байты число?
не могу найти что делает команда abyte. или это не команда?
http://chernyy.ru/blog/2010/04/19/pointers-and-references-in-c-and-cpp/
http://chernyy.ru/blog/2010/04/19/pointers-and-references-in-c-and-cpp/
большое спасибо за ссылку. доходчиво написано, но не сразу все понятно. я правильно понял этот код?
непонятно почему именно unsigned char если val unsigned long?
нельзя сразу указывать unsigned long?
непонятно почему именно unsigned char если val unsigned long?
нельзя сразу указывать unsigned long?
можно - попробуйте.
Вот только результат вас, скорее всего, не удовлетворит...
сам по себе адрес переменной одинаковая сущность вне зависимости от того на какую переменную он ссылается - все потому, что адрес указывает на первый байт в памяти вне зависимости от того сколько там этих байт
разница возникает когда вы обращаетесь к данным используя адрес. В строке присвоения:
если ваш abyte является ссылкой на тип byte, то при присвоении байт присваевается байту без каких-то преобразований - из памяти берется один байт и присваевается переменной byte0
А вот если вы определили abyte как ссылку на long, то в строке присвоения на самом деле компилятор сначала возьмет по адресу не один байт, а целых четыре! (длина long в ардуино), после этого из этих четырех байт попробует сделать переменную типа byte
Какие могут быть проблемы? Во превых не рекомендуется в лоб преобразовывать более длинный тип данных в более короткий (long в byte) не понимая с какими данными мы имеем дело. Могут быть нюансы преобразования и результат будет отличаться от ожидаемого.
Но это еще полбеды. В строке:
вы обращаетесь к "чужой" памяти! Ведь изначально long в памяти занимает 4 байта, обращаясь к третьему элементу массива вы прибавляете к адресу первого байта еще 3 - таким образом вы адресуете последний байт данных, но! так как ваша переменная типа (unsigned long*) вы берете не один байт, а целых четыре - тем самым вылезаете в "чужую" память на 3 байта. Последствия этого непредсказуемы, от некорректной работы скетча до его полного зависания. Так делать нельзя
Но это еще полбеды. В строке:
вы обращаетесь к "чужой" памяти! Ведь изначально long в памяти занимает 4 байта, обращаясь к третьему элементу массива вы прибавляете к адресу первого байта еще 3 - таким образом вы адресуете последний байт данных, но! так как ваша переменная типа (unsigned long*) вы берете не один байт, а целых четыре - тем самым вылезаете в "чужую" память на 3 байта. Последствия этого непредсказуемы, от некорректной работы скетча до его полного зависания. Так делать нельзя
Все еще хуже: определив abyte, как массив элементов unsigned long, при обращении к четвертому элементу массива (abyte[3] - это четвертый элемент массива, а не третий: не забываем, что индексация начинается с нуля!) вы обратитесь к области памяти, лежащей не на 3, а на 9-12 байтов дальше той области, в которой хранится искомая переменная, то есть далеко-далеко от той области памяти, которую мы намеревались исследовать побайтно. Почему? Потому, что при адресации элементов массивов используется не обычная арифметика, а арифметика указателей. Грубо - при увеличении индекса массива на единицу указатель смещается на длину типа данных, хранящихся в массиве (в нашем случае - на 4). Первый (с индексом 0) элемент массива покрывает исследуемую переменную, второй - оккупирует 4 байта сразу вслед за этой переменной (то есть занимает 1-й, 2-й, 3-й и 4-й байты вслед за исследуемой переменной), третий лежит на 5 байтов дальше последнего байта исследуемой переменной, и так далее...
да-да все еще хуже, согласен)
да-да все еще хуже, согласен)
мда. спасибо. совсем запутался. как то это сложно)
используем рабочий код
здесь мы считываем байты из unsigned long
а можем мы эти байты менять? например 3 байт хочу чтобы был FF, значение long соответственно изменится
мда. спасибо. совсем запутался. как то это сложно)
Да чего тут сложного-то:
представьте память в виде длинной книжной полки, а переменные - как собрания сочинений. Байты - совсем неплодовитые писатели (по одной книжечке), целые - двухтомники, длинные целые - четырехтомники, и так далее. Строки - ну это ваще полные собрания сочинений.
Байтовый массив - участок полки от n-й книжки до m-й...
Массив с длинными целыми - место, где подряд стоит несколько четырехтомников. Но как вы понимаете, такой участок полки можно и как байтовый массив рассматривать - просто число элементовы вырастет в четыре раза, например, вместо десяти четырехтомников вы уже будете видеть перед собой сорок отдельных томиков.
Или в рамках вашей задачи - стоит на полке четырехтомник писателя "val". Вы можете снять этот четырехтомник целиком, обратившись к переменной val. Но также можете дергать и по книжечке - всего-то необходимо проинструктировать библиотекаря, по сколько книг приносить (
unsigned
char
) и куда лесенку приставить (...abyte = ...
&val
).а можем мы эти байты менять? например 3 байт хочу чтобы был FF, значение long соответственно изменится
Разрешаю...
Измените - доложите о результатах.
а можем мы эти байты менять? например 3 байт хочу чтобы был FF, значение long соответственно изменится
Разрешаю...
Измените - доложите о результатах.
попытаюсь.
не до конца все равно понял запись
указатель abyte на переменную типа unsigned char = (ссылка на переменную типа unsigned char)адрес val
это правильно? после = не догоняю. указатель abyte равен адресу val. зачем перед этим в скобках указатель на переменную типа unsigned char?
блин как то мне реально тяжело дается. сделать чертеж и схему на шкаф с кучей оборудования серваками, упсами, преобразователями интерфейсов, внутренней разводкой и тп легко. а тут чувствую себя ребенком который учится читать)))) похоже надо какую нибудь книжку почитать может пойму
будет ли работать такая запись:
IMHO тут использование синтаксиса массивов - только запустывает. Это уже как раз "вывихи мозгов", нужно еще понимать что "массив это на самом деле указатель".
Так что я бы, раз пошли по пути указателей, то использовал бы оператор разименования указателя.
А еще, раз мы говорим "байты", то имеет смысл использовать именно "ардуино терминологию". Есть же специальный тип byte . Это синоним unsigned char, в арунине, только писать короче.
Выводит:
не до конца все равно понял запись
указатель abyte на переменную типа unsigned char = (ссылка на переменную типа unsigned char)адрес val
это правильно? после = не догоняю. указатель abyte равен адресу val. зачем перед этим в скобках указатель на переменную типа unsigned char?
Все правильно. Просто когда мы написали &val компилятор рассуждает примерно так.
1. Вижу &val, так как val у нас типа "unsigned long" значит это выражение возвращает "unsigned long *"
2. Но, его пытаются присвоить переменной типа "unsigned char*" - наверное это ошибка.
Когда же мы написали (unsigned char*)&val; мы сказали компилятору "вот то что вернут &val - считай типом "unsigned char*". Твое мнение по поводу того что вернул нам &val - нас не интересует.
В результате мы взяли только информацию об адресе, но забили на информацию о типе объекта куда указывал указатель.
Вообщем - компилятор пытается нас предостеречь от ошибки, а явным указанием типа мы говорим "спокуха, мы знаем что делаем".
"По умному" эта операция называется Приведение типа — Википедия . Когда у нас есть выражение одного типа, а нам нужно преобразовать его в другой тип.
Явное приведение типов
leshak спасибо большое за ответы и что не стал пинать неразбирающегося. большую часть уже понял, попозже еще раз перечитаю чтобы лучше уложилось в голове. за большое количество коментариев отдельное спасибо. так намного яснее
если уже пошел разговор о разбивке числа на байты(правильно ли здесь называть разбивкой? мы же не разбиваем а просто копируем отдельные байты) возникает вопрос. например нам нужно передать через nRF24L01 2 байта: 1 байт например для одного шима (у шима как раз удобно максимум 255) и 1 байт для второго. nRF24L01 передает за раз максимум один байт (возможно я ошибаюсь, было где то написано на форуме). но есть возможность передать 2 байта
как разбить число на байты уже понятно. а как 2 отдельных байта собрать в один, то есть не суммирую а поставив их рядом чтобы потом разбить. есть конечно более простой путь:
отправить сначала число, соответствующее 1 шиму(сами задаем число для условия). приемник будет знать что сейчас придет следующим байт первого шима. отправляем значение 1 шима. зачем число 2 шима, отправляем значение 2 шима
ну и по кругу.
первый вариант наверно все таки правильнее. в принятом числе первый байт всегда 1 шим, 2 байт всегда 2 шим
что вы думаете по этому поводу?
что вы думаете по этому поводу?
То что вам для начала нужно ознакомиться с разделом Программирование
массив (array)
nRF24L01 передает за раз максимум один байт (возможно я ошибаюсь, было где то написано на форуме).
что вы думаете по этому поводу?
То что вам для начала нужно ознакомиться с разделом Программирование
массив (array)
я пробовал подобным образом. не получилось. только одно значение 1 отправлялось. значит у меня какая то ошибка была. спасибо. попробую с помощью вашего кода
блин дошло почему. я забыл тогда указать цифру 2 (то что 2 байта отправлять), было один. и ожидал еще увидеть 2 байт)))
спасибо
nRF24L01 передает за раз максимум один байт (возможно я ошибаюсь, было где то написано на форуме).
32 байта это просто прекрасно. я предполагал изза ограничения 1 байт (где же я прочитал) в строке
мы отправляем по одному байту 2 раза. а библиотека потом его собирает и выдает уже целым
Ничего библиотека не собирает, а даже наоборот - разбивает, по одному байту, для того что бы поочередно помещать эти байты в регистр данных SPI и отправить в nRF24L01. А nRF24L01 массив до 32 байт всегда отправляется одним пакетом.
Ничего библиотека не собирает, а даже наоборот - разбивает, по одному байту, для того что бы поочередно помещать эти байты в регистр данных SPI и отправить в nRF24L01. А nRF24L01 массив до 32 байт всегда отправляется одним пакетом.
то есть nRF24L01 всегда отправляет 32 байта даже если все 32 байта не используют? это я так из интереса спрашиваю
Если используется статический размер данных 32 байта (так модуль по умолчанию настраивает библиотека) то да.
Есть два режима работы - фиксированная длина пакета и динамическая
в первом случае во время инициализации чипа вы указываете размер пакета и любая отправка по радио будет иметь эту длинну, но не обязательно 32 байта. Если вы хотите отправлять не более одного байта - можету указать один байт
в динамическом режиме каждый пакет может иметь свою длину