АЦП для Raspberry из Arduino NANO
- Войдите на сайт для отправки комментариев
Доброго времени суток господа! Стояла задача передать данные от датчика на малину по беспроводному каналу. Для решения этой задачи решено использовать два модуля nrf24l01. К малине подключить корректно не удалось - модуль принимал какую-то чушь, но если вмето малины его подключить к ардуинке, то все работает нормально. Поэтому не долго думая была заколхожена следующая схема: RPI <-i2c-nano(nrf24) <- nano(nrf24+датчик). Система работала стабильно, малина раз в 10 секунд читывала данные и отравляла в облако. Со временем потребовалось подключить к малине аналоговый датчик, но ацп под рукой не обнаружилось, а результат требовался здесь и сейчас. Поэтому роль ацп взяла на себя nano c nrf24, благо на борту у нее достаточно аналоговых пинов. Работа происходила по следующему алгоритму: малина отправляет номер порта на ардуино, а ардуино считывает с указанного порта данные и возвращает их малине. Все работает нормально какое то время, но потом выскакивает ошибка "bus.write_byte(SLAVE_ADDRESS, ord(chanel)) OSError: [Errno 121] Remote I/O error" и вместо разных данных с разных портов, малина получает данные одного (выскакивает ошибка). После перезагрузки ардуино все работает нормально какое то время.
Прогаю недавно, прошу тапками не кидаться
Код arduino
#include <Wire.h> #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> // https://github.com/maniacbug/RF24 #define SLAVE_ADDRESS 0x04 const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба" const int sensorPin = A0; //пин подключения датчика const long interval = 10000; //unsigned long previousMillis = 0; int smoke_level_0 = -1; // CO2 кухня int flag; RF24 radio(9, 10); // CE, CSN void setup(){ //Serial.begin(9600); pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(A4, INPUT); pinMode(A5, INPUT); pinMode(A6, INPUT); pinMode(A7, INPUT); Wire.begin(SLAVE_ADDRESS); Wire.onReceive(processMessage); Wire.onRequest(sendRadioReading); radio.begin(); delay(2); radio.setChannel(9); // канал (0-127) // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS // RF24_250KBPS на nRF24L01 (без +) неработает. // меньше скорость, выше чувствительность приемника. radio.setDataRate(RF24_1MBPS); // мощьность передатчика RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, radio.setPALevel(RF24_PA_HIGH); radio.openReadingPipe(1, pipe); // открываем первую трубу с индитификатором "pipe" radio.startListening(); // включаем приемник, начинаем слушать трубу } // radio.stopListening(); // останавливает приём (нужно перед началом передачи) void loop(){ //unsigned long currentMillis = millis(); if (radio.available()) { // проверяем не пришло ли чего в буфер. radio.read(&smoke_level_0, sizeof(smoke_level_0)); // читаем данные, указываем сколько байт читать } //if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED // previousMillis = currentMillis; // Serial.write(smoke_level_0); //Serial.write(sensorPin); //} } void processMessage(int n) { char message = Wire.read(); if (message =='0'){ flag = 0; } else if (message == '1') { flag = 1; } else if (message == '2') { flag = 2; } else if (message == '3') { flag = 3; } else if (message == '4') { flag = 4; } else if (message == '5') { flag = 5; } else if (message == '6') { flag = 6; } else if (message == '7') { flag = 7; } else if (message == '8') { flag = 8; } } void sendRadioReading() { if (flag == 8) { Wire.write(smoke_level_0); } else if (flag != 8) { Wire.write(analogRead(flag)); } }
Код малинки
import smbus import time bus = smbus.SMBus(1) SLAVE_ADDRESS = 0x04 def request_reading(chanel): bus.write_byte(SLAVE_ADDRESS, ord(chanel)) reading = int(bus.read_byte(SLAVE_ADDRESS)) #print(reading) return reading while True: x = request_reading('8') print(x) time.sleep(2) x = request_reading('0') print(x) time.sleep(5)
1. Почему бы вместо строк 65-99 не записать просто
? Это, конечно, "на скорость не влияет", но как-то попроще будет, всё ж одна строка, а не 35.
2. А вот что может влиять. Все переменные, которые используются и в программе, и в обработчике прерывания (наприер, flag, smoke_level_0) хорошо бы объявить "внезапно изменяемыми" - volatile.
Сделайте, а там посмотрим.
Проблема никуда не ушла
Не вижу кода
Код тот же самый, только с Вашими поправками.
Ардуино
Малина
Т.е. вы предлагаете кроме ардуины еще и с питоновской либой на малине потрахаться чтобы рассказать, где ошибка?
Уважаемый, я вам ни с чем трахаться не предлагаю. Питоновский код прикреплен здесь только для полноты картины и работает идеально, это проверено длительным промежутком времени на других проектах. Если внимательно прочитать код ошибки, видно, что малина не можеть отправить команду на указаный адрес, т.е., как мне кажется, проблема в ардуино.
Код тот же самый
Фига-се тот же самый! Как sendRadioReading-то поменялась.
Ну, давайте разбираться.
Во-первых, что у Вас за фигня в строка 74-10. Почему не нписать весто них всех
Это будет ровно то, что написано у Вас в этой чёртовой уйме строк. Только это неправильно.
Вы читаете analogRead'ом 10-тибитовое число, а передаёте 8-битовое. При таком продходе правильно будет передатваться только значения до 255. А любые значения от 256 и до 1023 будут передаваться неправильно.
Тоже самое в строках 69-70. В строке 69 Вы читаете 2 байта, а в строке 70 - передаёте только один.
Вы это понимаете?
Наконец, на стороне малины. В строках 8 и 10 Вы читаете по 1 байту. Учитывая, что Вы и передаетё по-одному, формально правильно, но на самом деле, Вам надо и передавать и читать по два байта.
Пока это сложно для меня. Можете показать, как передавать по два байта? какой нибудь простенький пример?
Ну, например, так: