>

ESP8266 Arduino 코어의 티커 라이브러리를 사용하여 핀 스위치를 아래와 같이 원하는 상태로 (비동기 적으로) 지연시키고 싶습니다. "여기"기능 정의에 대해 확신하고 일부 문서를 찾기가 어렵습니다. 지금까지 시도한 내용을 확인하십시오 :

#include <Ticker.h>
Ticker change_pin;
...
    uint8_t desired_state = 1;
    ...
    change_pin.attach_ms(100, [](uint8_t state_to_change_to){
        if( digitalRead(PIN) != state_to_change_to ) {
            digitalWrite(PIN, state_to_change_to);
        }
        else {
            change_pin.detach();
        }
    }, desired_state);

그러나 컴파일러의 소리 :

espIKEA:145: error: no matching function for call to 'Ticker::attach_ms(int, toogle_light(uint8_t)::__lambda0, uint8_t&)'
   }, des_state);
               ^
...
C:\Users\USER\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\Ticker/Ticker.h:45:7: note:   candidate expects 2 arguments, 3 provided
C:\Users\USER\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\Ticker/Ticker.h:62:7: note: template<class TArg> void Ticker::attach_ms(uint32_t, void (*)(TArg), TArg)
  void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
       ^
C:\Users\USER\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\Ticker/Ticker.h:62:7: note:   template argument deduction/substitution failed:
C:\Users\USER\Documents\Arduino\Scratch\pintest\pintest.ino:145:15: note:   mismatched types 'void (*)(TArg)' and 'toogle_light(u8)::__lambda0'
   }, des_state);
               ^

그러나 나는 그것에 대해 무엇을해야 하는지를 이해하기에는 지식이 거의 없습니다. 콜백 본문에 대해 별도의 함수를 사용하지 않으려 고합니다.

PS : 중요한 소스 파일은 여기에서 찾을 수 있습니다 : 티커 .h

  • 답변 # 1

    호출하려는 함수는 템플릿 함수입니다 :

    template<typename TArg>
    void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
    {
        ....
    }
    
    

    따라서 전달할 매개 변수 유형을 알려줘야합니다.

    change_pin.attach_ms<uint8_t>(100, [](uint8_t state_to_change_to) {
    //                     ^- tell the compiler about the parameter
        ....
    }, desired_state);
    
    

    <시간>

    하나 이상의 매개 변수를 전달하려면 : 라이브러리는 하나의 매개 변수 만 허용하므로 struct 를 작성합니다.  포인터를 전달하십시오.

    struct callback_parameter {
        int i;
        char *p;
    };
    
    

    그런 다음 이러한 구조체 중 하나를 만들어 주소를 전달합니다. 타이머가 실행될 때마다 구조체가 유효한지 확인해야합니다. 따라서 new 를 사용하십시오. static 또는 전 세계적으로 만들 수 있습니다.

    callback_parameter param; // global variable
    ...
    change_pin.attach_ms<callback_parameter *>(100, [](callback_parameter * state_to_change_to) {
        ....
    }, &param);
    
    

  • 답변 # 2

    람다 함수를 시도하는 것 같고 Arduino 컴파일러에는 너무 현대적입니다.

    그렇습니다 :

    change_pin.attach_ms(100, ????, desired_state);
    
    

    그냥 ???? 우리는 당신이 가지고있는 것을 정렬해야합니다 :

    void DoStuff (state_to_change_to)
    {
        if( digitalRead(PIN) != state_to_change_to ) 
        {
            digitalWrite(PIN, state_to_change_to);
        }
        else 
        {
            change_pin.detach();
        }
    }
    
    

    이제 자신 만의 함수 서명을 정의 할 수 없으며 callback_t 또는 callback_with_arg_t 여야합니다. "DoSTuff"함수가 callback_with_arg_t를 준수하도록하려면 다음과 같이 정의해야합니다.

    void DoStuff (void* argument);
    
    

    내부 기능을 의미하는 것은 다음과 같습니다 :

    void DoStuff (void* argument)
    {
        if (argument != NULL)
        {
           const uint8_t state_to_change_to = *argument;
           if( digitalRead(PIN) != state_to_change_to ) 
           .... As above.
    
    

    그건 말이 되나요?

    라이브러리는 콜백 역할을하는 함수의 서명을 정의합니다. 그렇지 않으면 모든 매개 변수를 제공 할 수 없습니다. void *는 형식 안전 동작에서 가장 중요한 문제를 해결하며 해당 매개 변수를 통과 할 수있는 항목을주의 깊게 제어하는 ​​한 괜찮습니다. 비동기식으로 작업하는 경우 데이터를 처리 할 때 데이터가 여전히 존재한다는 보장이 없으며 동적 메모리가 해제/삭제되었거나 변수가 범위를 벗어날 수있는 경우 항상 기억하십시오.

관련 자료

  • 이전 arduino - 추가 데이터를 보여주는 직렬 모니터
  • 다음 arduino - Arduino-ESP8266 (SoftwareSerial) 통신에서 전체 데이터를받지 못함