dparson55 / NRFLite

nRF24L01+ library with AVR 2 pin support, requiring very little code along with YouTube videos showing all available features.
MIT License
161 stars 27 forks source link

This library collide with servo. #76

Closed ghost closed 2 years ago

ghost commented 2 years ago

If I use this library I experience servo to stop after boot on 1 minutes.

I tested my code and confirmed only using servo is okay, but with NRFLite library servo stops moving after 1 minutes.

I think this is interrupt problem.

ghost commented 2 years ago

https://github.com/dparson55/NRFLite/issues/71

I referred this instructions

but this is not the way of solving problem..

my application need exact timing of servo.

so solution #1 doesn't look good to me.

and if I use solution #3, other applications use SPI protocol gets effect.

dparson55 commented 2 years ago

What you are describing probably isn't related to the #71 interrupt issue because it would only cause a servo to jitter, not cause a full break of the servo control. The interrupt issue will not get worse and worse over time, it will just cause the timing of the servo control pulses to be slightly off every now and then. What is it that makes you think it is an interrupt issue?

Since your code is working okay for 1 minute it sounds like a logic problem. If you can provide a basic tx and rx example to recreate the problem, I would be happy to look them over to see if I can help with a solution.

One quick thing you can do is put some print statements in to determine if a variable you are using is being changed correctly. If you can identify what is different about your variables before and after the servo stops responding, I would guess you will be able to solve the problem.

ghost commented 2 years ago

this is not a logic problem because I used LED to check my logic.

I tested like this code(simplified) : [code] if(~~~~) { servo.write(1500); digitalWrite(RED_LED,HIGH); } [/code]

LED still turned on by my logic but only servo don't move after certain times. time randomly changes.

I suspect something close global interrupt and not set again correctly, but it is just my thinking.

if you want, I will show you my code, but it is little bit complicated. and I changed my code to use timer register to manipulate servo. so I have to recover previous code in my brain.

but, it is very simple code there are only 3 components : servo, 2 color LED, NRF24L01

also, this is not hardware or power problem. I tested with code that eliminated NRF24L01 code. it worked more than 5 mins, more than 3 times.

this is the reason why I suspect interrupt problem.

ghost commented 2 years ago

I can also post the video if you want, but now I have to repair my code.

after repairing my code, I can post the video in monday.

ghost commented 2 years ago

Here I post my code :

//#define USE_TIMER_REGISTER

define USE_SERVO_LIBRARY

ifdef USE_TIMER_REGISTER

volatile uint8_t activated_servo = 0; volatile uint16_t pulse_width = 2777; //2999 volatile uint16_t period = 39999; //uint8_t 255

endif

ifdef USE_SERVO_LIBRARY

define HOOK_CLOSE_VALUE 1389

define HOOK_OPEN_VALUE 1722

include

Servo hook;

endif

define DELAY_TIME_HOOK_CLOSE 1000

define DELAY_TIME_HOOK_OPEN 1000 //unit : milliseconds.

include "SPI.h"

include "NRFLite.h"

const static uint8_t RADIO_ID = 0; // Our radio's id. The transmitter will send to this id. const static uint8_t PIN_RADIO_CE = 3; const static uint8_t PIN_RADIO_CSN = 4;

struct RadioPacket // Any packet up to 32 bytes can be sent. { uint8_t FromRadioId; //uint32_t OnTimeMillis; uint32_t hook_cmd_code; uint32_t FailedTxCount; };

NRFLite _radio; RadioPacket _radioData;

define USE_SS_LIGHT //SS_LIGHT KRGB3

//#define USE_5V_LED

ifdef USE_SS_LIGHT

define RED_PIN 7

define GREEN_PIN 6

endif

void setup() { //servo begin

ifdef USE_TIMER_REGISTER

DDRB |= B00000010; cli(); TCCR1A = 0; //normal counting mode. //TCCR1B = _BV(CS11); //set prescaler of 8. 16000000/8 = 2000000. TCCR1B = 0; TIMSK1 = 0; TCCR1B |= (1 << CS11); TCNT1 = 0;//clear the timer count OCR1A = 2999; //TIMSK1 = (1 << OCIE1A) | (1 << OCIE1B); TIMSK1 = (1 << OCIE1A); sei();

endif

/ By default, 'init' configures the radio to use a 2MBPS bitrate on channel 100 (channels 0-125 are valid). Both the RX and TX radios must have the same bitrate and channel to communicate with each other. You can run the 'ChannelScanner' example to help select the best channel for your environment. You can assign a different bitrate and channel as shown below. _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE2MBPS, 100) // THE DEFAULT _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE1MBPS, 75) _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE250KBPS, 0) /

ifdef USE_SS_LIGHT

pinMode(RED_PIN,OUTPUT);
pinMode(GREEN_PIN,OUTPUT);
//digitalWrite(RED_PIN, LOW);
//digitalWrite(GREEN_PIN,LOW);
digitalWrite(RED_PIN,HIGH);
digitalWrite(GREEN_PIN,HIGH);

endif

ifdef USE_SERVO_LIBRARY

hook.attach(9);
hook.write(1500);

endif

ifdef USE_SS_LIGHT

static unsigned long time_led_state_changed = 0;
static boolean is_red_led_turned_on = false;
if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))
{
    //Serial.println("Cannot communicate with radio");
    while (1)// Wait here forever.
    {
      if(millis() - time_led_state_changed > 100 && is_red_led_turned_on == true)
      {
        digitalWrite(RED_PIN,LOW);
        digitalWrite(GREEN_PIN,LOW);
        is_red_led_turned_on = false;
        time_led_state_changed = millis();
      }
      else if(millis() - time_led_state_changed > 100 && is_red_led_turned_on == false)
      {
        digitalWrite(RED_PIN,HIGH);
        digitalWrite(GREEN_PIN,LOW);
        is_red_led_turned_on = true;
        time_led_state_changed = millis();
      }
    }
}

endif

}

void loop() {

ifndef SERVO_TEST

    #ifdef USE_SS_LIGHT 
    static boolean is_no_signal = false;
    static boolean is_data_corrupted = false;
    static boolean is_receiving_open_code = false;
    static boolean is_receiving_close_code = false;
    static boolean is_hook_closed = false;
    static unsigned long time_started_receiving_open_cmd = 0;
    static unsigned long time_started_receiving_close_cmd = 0;
    static unsigned long time_started_no_signal = 0;
    static unsigned long time_started_data_corrupted = 0;
    static boolean is_orange_led_turned_on = false;
    static unsigned long time_led_state_changed = 0;
    uint8_t oldSREG = 0;

    while(_radio.hasData())
    { 
        is_no_signal = false;
        _radio.readData(&_radioData); // Note how '&' must be placed in front of the variable name.
        if(_radioData.FromRadioId == 1)
        {
              if(is_receiving_close_code == false && _radioData.hook_cmd_code == 1111) //1111 = close
              {
                time_started_receiving_close_cmd = millis();
                is_receiving_close_code = true;
              }
              else if(is_receiving_close_code == true && _radioData.hook_cmd_code != 1111)
              {
                is_receiving_close_code = false; 
              }

              if(is_receiving_close_code == true)
              {
                digitalWrite(RED_PIN,LOW);
                digitalWrite(GREEN_PIN,HIGH);
              }

              if(is_receiving_close_code == true && millis() - time_started_receiving_close_cmd > DELAY_TIME_HOOK_CLOSE)
              {
                #ifdef USE_TIMER_REGISTER
                if(!is_hook_closed)
                {
                  oldSREG = SREG;
                  cli();
                  pulse_width = 2777;
                  SREG = oldSREG;
                  is_hook_closed = true;
                }
                #endif
                #ifdef USE_SERVO_LIBRARY
                  hook.write(HOOK_CLOSE_VALUE);
                #endif
              }

              if(is_receiving_open_code == false && _radioData.hook_cmd_code == 2222) //2222 = open
              {
                time_started_receiving_open_cmd = millis();
                is_receiving_open_code = true;
              }
              else if(is_receiving_open_code == true && _radioData.hook_cmd_code != 2222)
              {
                is_receiving_open_code = false; 
              }

              if(is_receiving_open_code == true)
              {
                digitalWrite(RED_PIN,HIGH);
                digitalWrite(GREEN_PIN,LOW);
              }

              if(is_receiving_open_code == true && millis() - time_started_receiving_open_cmd > DELAY_TIME_HOOK_OPEN)
              {
                #ifdef USE_TIMER_REGISTER 
                if(is_hook_closed)
                {
                  oldSREG = SREG;
                  cli();
                  pulse_width = 3443; 
                  SREG = oldSREG;
                  is_hook_closed = false;
                }
                #endif
                #ifdef USE_SERVO_LIBRARY
                  hook.write(HOOK_OPEN_VALUE);
                #endif
              }

              if(is_receiving_open_code == false && is_receiving_close_code == false) 
              {
                is_data_corrupted = true;
                time_started_data_corrupted = millis();
              }
              else
              {
                is_data_corrupted = false;
              }
        }
    }

    if(is_no_signal == false)
    {
      is_no_signal = true;
      time_started_no_signal = millis();
    }

    if(  ((is_no_signal == true) && (millis()-time_started_no_signal > 1000)) || ( (is_data_corrupted == true) && (millis() - time_started_data_corrupted > 1000) ) ) 
    {
      if(((millis() - time_led_state_changed) > 100) && (is_orange_led_turned_on == false))
      {
        digitalWrite(RED_PIN,HIGH);
        digitalWrite(GREEN_PIN,HIGH);
        is_orange_led_turned_on = true;
        time_led_state_changed = millis();
      }
      else if(((millis() - time_led_state_changed) > 100) && (is_orange_led_turned_on == true))
      {
        digitalWrite(RED_PIN,LOW);
        digitalWrite(GREEN_PIN,LOW);
        is_orange_led_turned_on = false;
        time_led_state_changed = millis();
      }
      #ifdef USE_TIMER_REGISTER
      if(!is_hook_closed)
      {
        oldSREG = SREG;
        cli();
        pulse_width = 2777; //close
        SREG = oldSREG;
        is_hook_closed = true;
      }
      #endif
      #ifdef USE_SERVO_LIBRARY
          hook.write(HOOK_CLOSE_VALUE);
      #endif
    }

    //else 
    //{
    //  digitalWrite(RED_PIN,LOW);
    //  digitalWrite(GREEN_PIN,LOW);
    //}
    #endif//end of #ifdef USE_SS_LIGHT

endif //end of #ifndef SERVO_TEST

#ifdef SERVO_TEST
static unsigned long time_servo_changed = 0;
static boolean is_servo_down = false;

if(millis() - time_servo_changed > 5000)
{
  time_servo_changed = millis();
  if(is_servo_down == false)
  {
    //digitalWrite(RED_PIN,LOW);
    //digitalWrite(GREEN_PIN,HIGH);
    servo_values[0] = 1100;
    is_servo_down = true;
  }
  else if(is_servo_down == true)
  {
    //digitalWrite(RED_PIN,HIGH);
    //digitalWrite(GREEN_PIN,LOW);
    servo_values[0] = 1700;
    is_servo_down=false;
  }
}

endif

} //end of void loop

//39999 : 20msec //2999 : 1.5msec

ifdef USE_TIMER_REGISTER

ISR(TIMER1_COMPA_vect) { if(activated_servo == 0) { TCNT1 = 0; PORTB |= B00000010; //9 HIGH OCR1A = pulse_width; //OCR1A = 2999; activated_servo = 1; } else if(activated_servo == 1) { PORTB &= ~B00000010; //9 LOW //OCR1A = period; OCR1A = 39999; activated_servo = 0; } }

endif

ghost commented 2 years ago

Here is video link :

https://youtu.be/lT5ocwBBQX4

you can see servo stops to moving after 5 minutes.(usually it stops after 1 minutes. but this time I got lucky)

this is not the problem of servo because I changed servo already and if I use simple code just move the servo, it works after very long time.

ghost commented 2 years ago

also I tested with this code for check power issue :

include

Servo hook;

void setup() { // put your setup code here, to run once: hook.attach(9); pinMode(6,OUTPUT); pinMode(7,OUTPUT); //LED digitalWrite(6,HIGH); digitalWrite(7,LOW); }

void loop() { // put your main code here, to run repeatedly: delay(5000); digitalWrite(6,HIGH); digitalWrite(7,LOW); hook.writeMicroseconds(1200); delay(5000); digitalWrite(6,LOW); digitalWrite(7,HIGH); hook.writeMicroseconds(1700); }

ghost commented 2 years ago

as you can see in the video, this is not the problem of power or circuit...

servo still moves after 7 minutes :

https://youtu.be/0KIYbkHHaXs

dparson55 commented 2 years ago

Thanks for the videos and code. To help rule out some of the logic challenges can you try the simplified code below? Note I've used writeMicroseconds for consistency and moved the commands to change the servo position to the same if statements as the LED change statements. I also briefly looked through https://github.com/arduino-libraries/Servo and just wanted to confirm, are you using an ATmega328 microcontroller and is this the library you are using for the servo control?

    while (_radio.hasData())
    {
        is_no_signal = false;
        _radio.readData(&_radioData); // Note how '&' must be placed in front of the variable name.
        if (_radioData.FromRadioId == 1)
        {
            if (is_receiving_close_code == false && _radioData.hook_cmd_code == 1111) //1111 = close
            {
                time_started_receiving_close_cmd = millis();
                is_receiving_close_code = true;
            }
            else if (is_receiving_close_code == true && _radioData.hook_cmd_code != 1111)
            {
                is_receiving_close_code = false;
            }

            if (is_receiving_close_code == true)
            {
                digitalWrite(RED_PIN, LOW);
                digitalWrite(GREEN_PIN, HIGH);
                hook.writeMicroseconds(HOOK_CLOSE_VALUE);
            }

            if (is_receiving_open_code == false && _radioData.hook_cmd_code == 2222) //2222 = open
            {
                time_started_receiving_open_cmd = millis();
                is_receiving_open_code = true;
            }
            else if (is_receiving_open_code == true && _radioData.hook_cmd_code != 2222)
            {
                is_receiving_open_code = false;
            }

            if (is_receiving_open_code == true)
            {
                digitalWrite(RED_PIN, HIGH);
                digitalWrite(GREEN_PIN, LOW);
                hook.writeMicroseconds(HOOK_OPEN_VALUE);
            }
        }
    }
ghost commented 2 years ago

[1]"Note I've used writeMicroseconds for consistency"

<- Oh, How could I was stupid! I can't believe... sorry for your inconvinience. I Imeedietely changed my code from "hook.write" to "hook.writeMicroseconds"

but there was no change, the interesting thing is, the moving angle is same even after changed the code!

but... it didn't helped. the symtom was same.

[2]"moved the commands to change the servo position to same if statements as the LED change statements. " <- I tried this before and it didn't helped. there is no fault on "if" statement... but I will try soon.

<- I tried this just now and the result was same. I commented other servo writing code may affecting but still same.

[3]"I also briefly looked through https://github.com/arduino-libraries/Servo and just wanted to confirm, are you using an ATmega328 microcontroller and is this the library you are using for the servo control?" <- there was messages that servo library was duplicated, suddenly at one day(I had been using it very well, and did nothing) so I fiddled with servo library and reinstalled about 2~3 times. as soon as you say about servo library I barely rememberd it. I will dig into my servo library status and let you know soon.

and I'm using ATmega328p and use "arduino duemilanove or diecimilia" libary. I will plan to put my atmega328p on the PCB, and testing on stripboard. using 16Mhz crystal also. my stripboard is very same with arduino.

<- I checked my servo library and found I'm using the servo library that you said. I checked my compile status message on arduino IDE, and found this message : "Servo library version : 1.1.8, folder : C:\Users\xxx\Documents\Arduino\libraries\Servo" 1.1.8 is latest version, so it looks good.

I also replaced my servo library from 1.1.8(in the documents/arduino/libraries folder) to 1.1.7(originally located on the arduino folder)

but after I replace my servo library to original library installed with arduino IDE, still same symtoms.

I reinstalled servo library by clicking "upadate" on arduino IDE library manager, still same symtoms.

and please note that arduino servo library "writeMicroseconds" function have sei and cli inside. I suspect there something problem

ghost commented 2 years ago

if you want, I will post code I've tested.

but, as I said before, I tested this code and checked it is not logic issue :

if(~~~~) { servo.write(1500); digitalWrite(RED_LED,HIGH); }

ghost commented 2 years ago

if I use servotimer2(it uses timer2 instead of timer1.)library to manipulate servo, it works well most of the time. but sometimes NRFLite connection losts.

if I use timer register(OCR1A, TCCR1A, TCCR1B, etc) to directly manipulate servo, with sei() and cli() not to be interrupted by other process, It works well, but I didn't tested thoroughly.

and, this is the final code I successed to work for your reference(this works very well for more than 10 minutes, so I suspect the problem is colliding with servo library) :

define USE_TIMER_REGISTER

//#define USE_SERVO_LIBRARY

ifdef USE_TIMER_REGISTER

volatile uint8_t activated_servo = 0; volatile uint16_t pulse_width = 2777; volatile uint16_t period = 39999; volatile boolean time_to_radio_receive = false;

endif

ifdef USE_SERVO_LIBRARY

define HOOK_CLOSE_VALUE 1389

define HOOK_OPEN_VALUE 1722

include

Servo hook;

endif

define DELAY_TIME_HOOK_CLOSE 1000

define DELAY_TIME_HOOK_OPEN 1000 //unit : milliseconds.

include "SPI.h"

include "NRFLite.h"

const static uint8_t RADIO_ID = 0; // Our radio's id. The transmitter will send to this id. const static uint8_t PIN_RADIO_CE = 3; const static uint8_t PIN_RADIO_CSN = 4;

struct RadioPacket // Any packet up to 32 bytes can be sent. { uint8_t FromRadioId; //uint32_t OnTimeMillis; uint32_t hook_cmd_code; uint32_t FailedTxCount; };

NRFLite _radio; RadioPacket _radioData;

define USE_SS_LIGHT

//#define USE_5V_LED

ifdef USE_SS_LIGHT

define RED_PIN 7

define GREEN_PIN 6

endif

void setup() { //servo begin

ifdef USE_TIMER_REGISTER

DDRB |= B00000010; //this code should be read with ATMEGA328P manual. with that you can understand the code's meaning. cli(); //TCCRXA,B -> for Xth Timer TCCR1A = 0; //normal counting mode TCCR1B = 0; TIMSK1 = 0; TCCR1B |= (1 << CS11); TCNT1 = 0;//clear the timer count OCR1A = 2999; //TIMSK1 = (1 << OCIE1A) | (1 << OCIE1B); TIMSK1 = (1 << OCIE1A); sei();

endif

/ By default, 'init' configures the radio to use a 2MBPS bitrate on channel 100 (channels 0-125 are valid). Both the RX and TX radios must have the same bitrate and channel to communicate with each other. You can run the 'ChannelScanner' example to help select the best channel for your environment. You can assign a different bitrate and channel as shown below. _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE2MBPS, 100) // THE DEFAULT _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE1MBPS, 75) _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE250KBPS, 0) /

ifdef USE_SS_LIGHT

pinMode(RED_PIN,OUTPUT);
pinMode(GREEN_PIN,OUTPUT);
//digitalWrite(RED_PIN, LOW);
//digitalWrite(GREEN_PIN,LOW);
digitalWrite(RED_PIN,HIGH);
digitalWrite(GREEN_PIN,HIGH);

endif

ifdef USE_SERVO_LIBRARY

hook.attach(9);
hook.writeMicroseconds(1500);

endif

ifdef USE_SS_LIGHT

static unsigned long time_led_state_changed = 0;
static boolean is_red_led_turned_on = false;
if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))
{
    //Serial.println("Cannot communicate with radio");
    while (1)// Wait here forever.
    {
      if(millis() - time_led_state_changed > 100 && is_red_led_turned_on == true)
      {
        digitalWrite(RED_PIN,LOW);
        digitalWrite(GREEN_PIN,LOW);
        is_red_led_turned_on = false;
        time_led_state_changed = millis();
      }
      else if(millis() - time_led_state_changed > 100 && is_red_led_turned_on == false)
      {
        digitalWrite(RED_PIN,HIGH);
        digitalWrite(GREEN_PIN,LOW);
        is_red_led_turned_on = true;
        time_led_state_changed = millis();
      }
    }
}

endif

}

void loop() {

ifndef SERVO_TEST

    #ifdef USE_SS_LIGHT
    static boolean is_no_signal = false;
    static boolean is_data_corrupted = false;
    static boolean is_receiving_open_code = false;
    static boolean is_receiving_close_code = false;
    static boolean is_hook_closed = false;
    static unsigned long time_started_receiving_open_cmd = 0;
    static unsigned long time_started_receiving_close_cmd = 0;
    static unsigned long time_started_no_signal = 0;
    static unsigned long time_started_data_corrupted = 0;
    static boolean is_orange_led_turned_on = false;
    static unsigned long time_led_state_changed = 0;
    uint8_t oldSREG = 0;

    //while(_radio.hasData())
    if(_radio.hasData() && time_to_radio_receive == true)//only gets data when servo is resting. suspecting interrupt collision.
    {
        #ifdef USE_TIMER_REGISTER
          time_to_radio_receive = false;
        #endif
        is_no_signal = false;
        _radio.readData(&_radioData); // Note how '&' must be placed in front of the variable name.
        //msg += _radioData.hook_cmd_code;
        if(_radioData.FromRadioId == 1)
        {
              if(is_receiving_close_code == false && _radioData.hook_cmd_code == 1111) //1111 = close
              {
                time_started_receiving_close_cmd = millis();
                is_receiving_close_code = true;
              }
              else if(is_receiving_close_code == true && _radioData.hook_cmd_code != 1111)
              {
                is_receiving_close_code = false; 
              }

              if(is_receiving_close_code == true)
              {
                digitalWrite(RED_PIN,LOW);
                digitalWrite(GREEN_PIN,HIGH);
                if(millis() - time_started_receiving_close_cmd > DELAY_TIME_HOOK_CLOSE)
                {
                  #ifdef USE_TIMER_REGISTER
                  if(!is_hook_closed)
                  {
                    oldSREG = SREG;
                    cli();
                    pulse_width = 2777; //close value 1389 pwm.
                    SREG = oldSREG;
                    is_hook_closed = true;
                  }
                  #endif
                  //#ifdef USE_SERVO_LIBRARY
                  //  hook.writeMicroseconds(HOOK_CLOSE_VALUE);
                  //#endif
                }
              }

              if(is_receiving_open_code == false && _radioData.hook_cmd_code == 2222) //2222 = open
              {
                time_started_receiving_open_cmd = millis();
                is_receiving_open_code = true;
              }
              else if(is_receiving_open_code == true && _radioData.hook_cmd_code != 2222)
              {
                is_receiving_open_code = false; 
              }

              if(is_receiving_open_code == true)
              {
                digitalWrite(RED_PIN,HIGH);
                digitalWrite(GREEN_PIN,LOW);
                if(millis() - time_started_receiving_open_cmd > DELAY_TIME_HOOK_OPEN)
                {
                    #ifdef USE_TIMER_REGISTER 
                    if(is_hook_closed)
                    {
                      //oldSREG = SREG;
                      cli();
                      pulse_width = 3443; //open value는 1722.
                      SREG = oldSREG;
                      is_hook_closed = false;
                    }
                    #endif
                    #ifdef USE_SERVO_LIBRARY
                      hook.writeMicroseconds(HOOK_OPEN_VALUE);
                    #endif
                }
              }

              if(is_receiving_open_code == false && is_receiving_close_code == false)
              {
                is_data_corrupted = true;
                time_started_data_corrupted = millis();
              }
              else
              {
                is_data_corrupted = false;
              }
        }
    }        

    if(is_no_signal == false)
    {
      is_no_signal = true;
      time_started_no_signal = millis();
    }

    if(  ((is_no_signal == true) && (millis()-time_started_no_signal > 1000)) || ( (is_data_corrupted == true) && (millis() - time_started_data_corrupted > 1000) ) ) 
    {
      if(((millis() - time_led_state_changed) > 100) && (is_orange_led_turned_on == false))
      {
        digitalWrite(RED_PIN,HIGH);
        digitalWrite(GREEN_PIN,HIGH);
        is_orange_led_turned_on = true;
        time_led_state_changed = millis();
      }
      else if(((millis() - time_led_state_changed) > 100) && (is_orange_led_turned_on == true))
      {
        digitalWrite(RED_PIN,LOW);
        digitalWrite(GREEN_PIN,LOW);
        is_orange_led_turned_on = false;
        time_led_state_changed = millis();
      }
      static unsigned long reconnect_time = 0;
      if(millis() - reconnect_time > 5000)
      {
        _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN); 
        reconnect_time = millis();
      }

      #ifdef USE_TIMER_REGISTER
      if(!is_hook_closed)
      {
        oldSREG = SREG;
        cli();
        pulse_width = 2777; //close
        SREG = oldSREG;
        is_hook_closed = true;
      }
      #endif
      #ifdef USE_SERVO_LIBRARY
          hook.writeMicroseconds(HOOK_CLOSE_VALUE);
      #endif
    }

    //else 
    //{
    //  digitalWrite(RED_PIN,LOW);
    //  digitalWrite(GREEN_PIN,LOW);
    //}
    #endif//end of #ifdef USE_SS_LIGHT

endif //end of #ifndef SERVO_TEST

#ifdef SERVO_TEST
static unsigned long time_servo_changed = 0;
static boolean is_servo_down = false;

if(millis() - time_servo_changed > 5000)
{
  time_servo_changed = millis();
  if(is_servo_down == false)
  {
    //digitalWrite(RED_PIN,LOW);
    //digitalWrite(GREEN_PIN,HIGH);
    servo_values[0] = 1100;
    is_servo_down = true;
  }
  else if(is_servo_down == true)
  {
    //digitalWrite(RED_PIN,HIGH);
    //digitalWrite(GREEN_PIN,LOW);
    servo_values[0] = 1700;
    is_servo_down=false;
  }
}

endif

} //end of void loop

//39999 : 20msec //2999 : 1.5msec

ifdef USE_TIMER_REGISTER

ISR(TIMER1_COMPA_vect) { if(activated_servo == 0) { TCNT1 = 0; PORTB |= B00000010; //9 HIGH OCR1A = pulse_width; //OCR1A = 2999; activated_servo = 1; } else if(activated_servo == 1) { PORTB &= ~B00000010; //9 LOW //OCR1A = period; OCR1A = 39999; activated_servo = 0; time_to_radio_receive = true; } }

endif

dparson55 commented 2 years ago

if you want, I will post code I've tested. but, as I said before, I tested this code and checked it is not logic issue

Your original code was tough (for me at least) to go through since it wasn't formatted and contained a lot of extra logic that isn't related to the radio and servo control. Still though, I did spend the time to format and go through it and remove excess code, and am just trying to help with the code you provided, so let's continue to use it.

If the suggestion I made provides no value, another troubleshooting step would be to run detach and attach before attempting to control the servo again. This will help identify if the initial setup steps performed by the servo library are being lost.

    while (_radio.hasData())
    {
        is_no_signal = false;
        _radio.readData(&_radioData); // Note how '&' must be placed in front of the variable name.
        if (_radioData.FromRadioId == 1)
        {
            if (is_receiving_close_code == false && _radioData.hook_cmd_code == 1111) //1111 = close
            {
                time_started_receiving_close_cmd = millis();
                is_receiving_close_code = true;
            }
            else if (is_receiving_close_code == true && _radioData.hook_cmd_code != 1111)
            {
                is_receiving_close_code = false;
            }

            if (is_receiving_close_code == true)
            {
                digitalWrite(RED_PIN, LOW);
                digitalWrite(GREEN_PIN, HIGH);
                hook.detach();
                hook.attach(9);
                hook.writeMicroseconds(HOOK_CLOSE_VALUE);
            }

            if (is_receiving_open_code == false && _radioData.hook_cmd_code == 2222) //2222 = open
            {
                time_started_receiving_open_cmd = millis();
                is_receiving_open_code = true;
            }
            else if (is_receiving_open_code == true && _radioData.hook_cmd_code != 2222)
            {
                is_receiving_open_code = false;
            }

            if (is_receiving_open_code == true)
            {
                digitalWrite(RED_PIN, HIGH);
                digitalWrite(GREEN_PIN, LOW);
                hook.detach();
                hook.attach(9);
                hook.writeMicroseconds(HOOK_OPEN_VALUE);
            }
        }
    }

I spent some time going through the servo library and unfortunately I don't see where it might be conflicting with the SPI and NRFLite libraries. Even if the global interrupt flag is disabled when the servo library saves it (https://github.com/arduino-libraries/Servo/blob/master/src/avr/Servo.cpp#L289), NRFLite will re-enable it every time it communicates with the radio (https://github.com/dparson55/NRFLite/blob/master/src/NRFLite.cpp#L592).

Maybe worse case, you can use a different radio library and I will update the NRFLite readme with a note that it is not compatible with the servo library. I don't understand what the servo library is doing and how NRFLite would be impacting it.

ghost commented 2 years ago

anyway I solved my problem as I mentioned above.

direct manipulating servo with timer register(OCR1A) doesnt conflict with NRFLite library. I will use this code.

and sorry for my tough code.

Since the servo library is not clearly confirmed to conflict with NRFLite library, it may not be necessary to include the statement in readme file. But if there is someone similar to me, I hope my case can be referenced.

dparson55 commented 2 years ago

Ok good luck with the rest of the project.