#1 2017-04-18 13:56:21

VS
Участник
Зарегистрирован: 2015-08-07
Сообщений: 11

nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

Народ, всем привет.
Благодоря интернетам и чужим скетчам смог за 2 месяца собрать радиоуправление на свой карповый кораблик. Все работает как мне того хотелось, но нет гарантии, что мой кораблик не уйдет за горизонт, при пропадании связи. Мотор управляется простым замыканием реле. (Не хочу ШИМ - хочу реле!)
Если возможно подскажите, как можно сделать, чтоб при пропадании (сбое) связи в моем скетче пины 6,7,8 принимали значение HIGH
Естесно я новичок. Уже перепробовал все, что мне могло в голову прийти, а результата 0.

Код приемника:

/*
4 серво + 3 реле
Реле срабатывают в зависимости от положения джостика 1 по оси У на передатчике
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Servo.h>


RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9,53); // для Меги

byte recieved_data[6]; // массив принятых данных
byte servo_ruly = 2; // сервопривод на 2 цифровом (право/лево руля)
byte kt803 = 3; // сервопривод на 3 цифровом (регулятор мощности)
byte servo_left = 4; // сервопривод на 4 цифровом (выгруз левый)
byte servo_right = 5; // сервопривод на 5 цифровом (выгруз правый)

byte rele1 = 6; // реле на 6 цифровом (полный вперед катера)
byte rele2 = 7; // реле на 7 цифровом (малый вперед катера)
byte rele3 = 8; // реле на 8 цифровом (малый назад катера)
//byte relay = ?; // реле на ? цифровом (запасной на фару, если возьму мегу)

Servo myservo1;
Servo myservo2;
Servo myservo3;
Servo myservo4;

byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб

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

  //pinMode(relay, OUTPUT); // настроить пин реле как выход
  pinMode(rele1, OUTPUT); // настроить пин реле как выход
  pinMode(rele2, OUTPUT); // настроить пин реле как выход
  pinMode(rele3, OUTPUT); // настроить пин реле как выход
  pinMode(servo_ruly, OUTPUT); // настроить пин сервопривода как выход
  pinMode(kt803, OUTPUT); // настроить пин сервопривода как выход
  pinMode(servo_left, OUTPUT); // настроить пин сервопривода как выход
  pinMode(servo_right, OUTPUT); // настроить пин сервопривода как выход

   digitalWrite(rele1, HIGH);
   digitalWrite(rele2, HIGH);
   digitalWrite(rele3, HIGH);

  myservo1.attach(servo_ruly);
  myservo2.attach(kt803);
  myservo3.attach(servo_left);
  myservo4.attach(servo_right);

      myservo1.write(90);
      myservo3.write(10);
      myservo4.write(10);
          
  radio.begin(); //активировать модуль
  radio.setAutoAck(1);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах

  radio.openReadingPipe(1, address[0]);     //хотим слушать трубу 0
  radio.setChannel(0x60);  //выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  //при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp(); //начать работу
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
}

void loop() {
  byte pipeNo;

  while ( radio.available(&pipeNo)) {  // слушаем эфир со всех труб
    radio.read( &recieved_data, sizeof(recieved_data) );         // чиатем входящий сигнал
    
    //digitalWrite(relay, recieved_data[0]); // подать на реле сигнал с 0 места массива то бишь 0 или 1
    myservo1.write(recieved_data[1]); // повернуть серво на угол с 1 элемента массива
    myservo2.write(recieved_data[2]); // повернуть серво на угол с 2 элемента массива
    myservo3.write(map((recieved_data[3]), 0, 115, 10, 160)); // повернуть серво на угол с 3 элемента массива
    myservo4.write(map((recieved_data[3]), 140, 255, 10, 160));// повернуть серво на угол с 3 элемента массива

    if ((recieved_data[4])>=134 && (recieved_data[4])<254) // (полный вперед катера)
    {
    digitalWrite(rele1, HIGH);
    digitalWrite(rele2, LOW);
    } 
        else if ((recieved_data[4])>=254) // (малый вперед катера)
    {
    digitalWrite(rele2, HIGH);
    digitalWrite(rele1, LOW);
    } 
            else if ((recieved_data[4])<=75) // (малый назад катера)
    {
    digitalWrite(rele3, LOW);
    } 
                else if ((recieved_data[4])>75 && (recieved_data[4])<134) // стоп мотор
    {    
    digitalWrite(rele1, HIGH);
    digitalWrite(rele2, HIGH);
    digitalWrite(rele3, HIGH);
    }
  }
}

#2 2017-04-18 13:58:01

VS
Участник
Зарегистрирован: 2015-08-07
Сообщений: 11

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

на "всякий" случай код передатчика:

/*   
4 серво + 3 реле
Реле срабатывают в зависимости от положения джостика 1 по оси У
*/

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб

#define JOYSTICK_1_X A0
#define JOYSTICK_1_Y A1
#define JOYSTICK_2_X A2
#define JOYSTICK_2_Y A3
#define POTENT_KT803 A4

byte button = 3;  // кнопка на 3 цифровом (фара)

byte transmit_data[6]; // массив, хранящий передаваемые данные
byte latest_data[6]; // массив, хранящий последние переданные данные
boolean flag; // флажок отправки данных

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

  pinMode(button, INPUT_PULLUP); // настроить пин кнопки

  radio.begin(); //активировать модуль
  radio.setAutoAck(1);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах

  radio.openWritingPipe(address[0]);   //мы - труба 0, открываем канал для передачи данных
  radio.setChannel(0x60);  //выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS

  radio.powerUp(); //начать работу
  radio.stopListening();  //не слушаем радиоэфир, мы передатчик
}

void loop() {

  transmit_data[0] = !digitalRead(button); // инвертированный (!) сигнал с кнопки
  transmit_data[1] = map(analogRead(JOYSTICK_1_X), 0, 1023, 60, 120); // значение право/лево руля
  transmit_data[2] = map(analogRead(POTENT_KT803), 0, 1023, 10, 160); // регулятор мощности малого хода KT803
  transmit_data[3] = map(analogRead(JOYSTICK_2_X), 0, 1023, 0, 255); // выгруз левый/правый
  transmit_data[4] = map(analogRead(JOYSTICK_1_Y), 0, 1023, 0, 255); // полный/малый вперед + малый назад катера
  transmit_data[5] = map(analogRead(JOYSTICK_2_Y), 0, 1023, 0, 255); // запасной
  
  for (int i = 0; i < 6; i++) { // в цикле от 0 до числа каналов
    if (transmit_data[i] != latest_data[i]) { // если есть изменения в transmit_data
      flag = 1; // поднять флаг отправки по радио
      latest_data[i] = transmit_data[i]; // запомнить последнее изменение
    }
  }

  if (flag == 1) {
    radio.powerUp(); // включить передатчик
    radio.write(&transmit_data, sizeof(transmit_data)); // отправить по радио
    flag = 0; //опустить флаг
    radio.powerDown(); // выключить передатчик
  }

}

#3 2017-04-18 16:36:14

NoName
Customer
Из Київ
Зарегистрирован: 2014-07-08
Сообщений: 1,220

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

Сделайте возврат по gps на стартовую точку, где то я такое видел,  контроль по пингу

#4 2017-04-19 00:01:10

NoName
Customer
Из Київ
Зарегистрирован: 2014-07-08
Сообщений: 1,220

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

нашел старую наработку,  но я ее не проверял
пример кода, как по векторам ездить разберетесь сами,
если работает, то только для северного полушария

#include "extern.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
//--------------------------------------------------------------------
double SearchDataType(char* str, int type  )
{

  int len;
  int temp_type;
  int temp_pos;
  int foo;
  char  ret[100];
  
  len = strlen(str);
  temp_type = 0;
  
  for ( foo = 0; foo < len; foo++)
  {
   if ( *((char*)str+foo) == ',' )
    {
       temp_type++;
       if ( temp_type == type ) break;
    }
  }
  
  temp_pos = 0;
  foo++;
  
  for (  ; foo < len; foo++)
  {
   if ( *((char*)str+foo) == ',' )
        break;
   
   
   ret[temp_pos] = *((char*)str+foo);
   temp_pos++;
 
  }
  ret[temp_pos] = '\0'; 
  
  
  
  return( atof ( ret )  );
}
//--------------------------------------------------------------------
int STR_SEARCH( char* STR, char* COMPARE )
{
   int foo_len;
   int max_len;
   int ok;
   int len_compare;
   len_compare = strlen(COMPARE);
   max_len = strlen( STR );
   
   ok = 0;

   for ( foo_len = 0; foo_len < max_len; foo_len++ )
   {
       if ( STR[foo_len]  == COMPARE[ok] ) ok++;
           else ok = 0;
        if ( ok == len_compare ) return ( 1 );
   }
   return ( 0 );   
}

short ReloadDataGPS( void )
{
 //                0     1      2 3       4 5        6 7     8     9      10  11 12
 // char *test = "$GPRMC,XXXXXX,A,XXXX.451,N,XXXXX.132,W,XXX.025,054.7,XXXXXX,020.3,E*68";
  int foo;
  long temp_long;
  char*  temp_str;

  System.Event&=~GPSDATA; 
  
 // for ( foo = 0; foo < sizeof(System.GPS.GPRMC); foo++ )
 //                System.GPS.GPRMC[foo] = *((char*)test+foo); 

 // if ( STR_SEARCH( (char*)System.GPS.GPRMC,"$GPRMC")  ) 
 {
  //  temp_str = SearchDataType( (char*)System.GPS.GPRMC,2 );
  //  if ( *(char*)temp_str != 'A' ) return(0);
 //   temp_str = SearchDataType( (char*)System.GPS.GPRMC,1 );
 //   temp_long = atol(temp_str);

   System.GPS.Time = (temp_long/10000)*60*60;
   System.GPS.Time += ((temp_long/100)%100)*60;
   System.GPS.Time += (temp_long%100);
   
   
   System.GPS.Latitude   = SearchDataType( (char*)System.GPS.GPRMC,3 );
   System.GPS.Longitude =  SearchDataType( (char*)System.GPS.GPRMC,5 );
 
   System.GPS.Speed =  SearchDataType( (char*)System.GPS.GPRMC,7 );
   System.GPS.NowAngle =  SearchDataType( (char*)System.GPS.GPRMC,8 );
   System.GPS.Speed *= 1.852; 
 
  System.GPS.SpeedZone = 0;
  if ( System.GPS.Speed > 60 )  System.GPS.SpeedZone = 1; 
  if ( System.GPS.Speed > 65 )  System.GPS.SpeedZone = 2; 
  if ( System.GPS.Speed > 70 )  System.GPS.SpeedZone = 3; 
 } 

 return(1);

}

//----------------------------------------------------
//    ЧЧЧЧ.7243
// in ddmm.mmm
// out dd.ddddd
double ConvertToWGS84( double in )
{
  double out; 

  double HI; 
  double LO; 
  
  HI =  (int)(in/100 ) ; // получили градусы
  in = in / 100.0;
  LO = in - (int)( in );
  LO = LO*100.0 / 60.0;
  
  out = HI + LO;  
  return ( out );
}
//----------------------------------------------------
 
 double DegToRad(double x) 
    { 
        const double PIx = 3.141592653589793; 
        return (x * PIx / 180.0); 
    } 

 double RadToDeg (double x) 
    { 
        const double PIx = 3.141592653589793; 
        return (x * 180.0 / PIx  ); 
    } 
 


 double gps2m(double lat1, double lon1, double lat2, double lon2) 
 {

     double RADIO = 6378.16; 
     double rlat1 = DegToRad(ConvertToWGS84(lat1));    
     double rlon1 = DegToRad(ConvertToWGS84(lon1));    
     double rlat2 = DegToRad(ConvertToWGS84(lat2));    
     double rlon2 = DegToRad(ConvertToWGS84(lon2));    

     double dlon = rlon2 - rlon1; 
     double dlat = rlat2 - rlat1; 
     double a = (sin(dlat / 2.0) * sin(dlat / 2.0)) + cos(rlat1) * cos(rlat2) * (sin(dlon / 2.0) * sin(dlon / 2.0)); 
     double angle = 2.0 * atan2(sqrt(a), sqrt(1.0 - a)); 
     return (angle * RADIO); 
 }

double CalcAsimut( double lat1, double lon1, double lat2, double lon2 )
{
// вычисление начального азимута
 double PIx = 3.141592653589793; 

     double rlat1 = DegToRad(ConvertToWGS84(lat1));    
     double rlon1 = DegToRad(ConvertToWGS84(lon1));    
     double rlat2 = DegToRad(ConvertToWGS84(lat2));    
     double rlon2 = DegToRad(ConvertToWGS84(lon2));    
 
 
    double cl1 =  cos(rlat1);
    double cl2 =  cos(rlat2);
    double sl1 =  sin(rlat1);
    double sl2 =  sin(rlat2);
    double delta = ( rlon2 - rlon1 );
    double cdelta =  cos(delta);
    double sdelta =  sin(delta);
 /*
    double x = (cl1*sl2) - (sl1*cl2*cdelta); 
    double y = sdelta*cl2; 
    double z = atan(-y/x); 
    if ( x < 0 ) z = z + 180.0;
    z = -((z + 180.0) - 180.0);
// z = -((z + 180.0)%360 - 180.0);
// double anglerad2 = z - ((2.0*PIx)*( floor(z/(2.0*PIx)) ));
 double anglerad2 = z - ((2.0*PIx)*(  floor(z/(2.0*PIx)) ));

    double angledeg = (anglerad2*180.0)/PIx;
*/
    
// #вычисление начального азимута
 double x = (cl1*sl2) - (sl1*cl2*cdelta);
 double y = sdelta*cl2;
 double z =   ( atan(-y/x));

if (x < 0 )
    z = z + 180.0;

  double z2 = (z+180.0)  - 180.0;
 //  z2 = - radians(z2);
 double anglerad2 = z2 - ((2*PIx)* floor((z2/(2*PIx))) );
 double angledeg = (anglerad2*180.0)/PIx;
    
 return ( angledeg );
}


void CalcHeadingDist(double lat1, double lon1, double lat2, double lon2, double *outAngle, double *outDist)
{
  double radlat1, radlat2, radlon1, radlon2;
  radlat1 = DegToRad(ConvertToWGS84(lat1));
  radlon1 = DegToRad(ConvertToWGS84(lon1));
  radlat2 = DegToRad(ConvertToWGS84(lat2));
  radlon2 = DegToRad(ConvertToWGS84(lon2));

  double cl1 = cos(radlat1);
  double cl2 = cos(radlat2);
  double sl1 = sin(radlat1);
  double sl2 = sin(radlat2);
  double delta = radlon2 - radlon1;
  double cdelta = cos(delta);
  double sdelta = sin(delta);

  double p1 = pow((cl2*sdelta),2);
  double p2 = pow(((cl1*sl2) - (sl1*cl2*cdelta)),2);
  double p3 = pow((p1 + p2),0.5);
  double p4 = sl1*sl2;
  double p5 = cl1*cl2*cdelta;
  double p6 = p4 + p5;
  double p7 = p3 / p6;
  double anglerad = atan(p7);
  *outDist = anglerad*6367;

  double x = (cl1*sl2) - (sl1*cl2*cdelta);
  double y = sdelta*cl2;

  double z = RadToDeg(atan((-y/x)));
  if ( x < 0 ) z = z+180.0;
  z = -(DegToRad((  z + 180  % 360 - 180.0)));
  double anglerad2 = z - ( (2.0*3.14159265)*  floor(z/(2.0*3.14159265)) );
  *outAngle = (anglerad2*180.0)/3.14159265;

}

хорошо что напомнили, мне тоже такая штука нужна )

последняя корекция от спеца по вебдизайну, плохо закончилась для C++,  печально (

Редактировался NoName (2017-04-19 00:03:20)

#5 2017-04-20 09:41:02

VS
Участник
Зарегистрирован: 2015-08-07
Сообщений: 11

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

NoName пишет:

нашел старую наработку,  но я ее не проверял
пример кода, как по векторам ездить разберетесь сами,

Спасибо. Пока страшно смотреть на такой большой код smile, но в длинной перспективе думал об этом.

#6 2017-04-20 12:30:37

NoName
Customer
Из Київ
Зарегистрирован: 2014-07-08
Сообщений: 1,220

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

Дето есть на форуме тема с моей недоделанный лодкой(  писать код я еще могу найти время, а вот ручками поработать, собрать, проверить, совсем нет возможности, если моя основа вам подходит давайте скооперироваться, пока ноут сгорел но что-то придумаю, я обязан спустить лодку на майские, так что если есть желание давайте скооперируемся ) тему потом поищу, с телефона неудобно)

#7 2017-06-11 13:45:50

condensator89
Участник
Зарегистрирован: 2017-06-11
Сообщений: 25

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

VS пишет:

Если возможно подскажите, как можно сделать, чтоб при пропадании (сбое) связи в моем скетче пины 6,7,8 принимали значение HIGH.

Очень просто:

1) в конце setup() установи значение таймаута на отсутствие приема: mytimeout=500; //в милисекундах
и last_time=0; 
2) в основной программе запоминай время последнего принятого пакета last_time=millis();
3) вычисли разницу времени между last_time и текущим временем dt=millis()-last_time;
4) if(dt >= mytimeout) { /* отключи то, что хотел отключить*/;;; } else;

5) помни про возможное переполнение счетчика у функции millis()

#8 2017-06-12 11:41:39

Вячеслав Азаров
Участник
Из Запорожье
Зарегистрирован: 2017-05-25
Сообщений: 406

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

В этом диапазоне работает так же Wi-Fi, Bluetooth и микроволновые печки. Для отстройки от помех и уменьшения их влияния используют, довольно сложные, методы радиосвязи, известные под термином "расширение спектра". Можно ли реализовать на NRF24 чередование каналов связи, как это сделано в Bluetooth и GSM сказать трудно. А повторные передачи на зашумленном канале дело мало полезное.

Редактировался Вячеслав Азаров (2017-06-12 11:42:25)

#9 2017-09-13 11:26:38

MickNich
Участник
Из Полтава
Зарегистрирован: 2017-09-13
Сообщений: 1

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

"Wi-Fi, Bluetooth и микроволновые печки." - только всё это как правило отсутствует на рыболовном пруду...

http://forum.arduino.ua/viewtopic.php?id=790 - тема Нонейма

Редактировался MickNich (2017-09-13 11:32:01)

#10 2017-09-13 12:45:01

Green
Участник
Зарегистрирован: 2015-11-08
Сообщений: 279

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

А у меня Wi-Fi роутер в метре стоит, и ничё. NRF24 работает даже на каналах используемых роутером. Чудеса.)

#11 2017-09-13 14:24:03

Вячеслав Азаров
Участник
Из Запорожье
Зарегистрирован: 2017-05-25
Сообщений: 406

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

Green пишет:

А у меня Wi-Fi роутер в метре стоит, и ничё. NRF24 работает даже на каналах используемых роутером. Чудеса.)

Слабонагруженный Wi-Fi занимет канал на 1 - 10 % времени (сам измерял). Так что NRF24 "встряет" в тишину. Но если их в зоне радио-видимости десяток, совсем другое дело. Все зависит от электромагнитной обстановки местности. Блутуз в этом отношении лучше, но дороже и сложнее.

#12 2017-09-13 15:35:40

NoName
Customer
Из Київ
Зарегистрирован: 2014-07-08
Сообщений: 1,220

Re: nrf24L01+ Помогите в коде прописать защиту от пропадания связи.

Вячеслав Азаров, у Вас есть опыт работы с https://www.bluetooth.com/specifications/bluetooth-core-specification ?
не все понятно в  https://www.bluetooth.org/DocMan/handle … _id=421043

Быстрое сообщение

Введите сообщение и нажмите Отправить

Подвал раздела