지난번에는 기본적인 통신 테스트를 마쳤고 이번에는 고정된 테스트값이 아니라 정말로 아날로그 스틱에서 값을 읽어와 NRF24L01 모듈로 송수신하여 테스트 해봤다.

일단 내가 만들고자 하는 V1.0 의 송수신기는 아래 그림과 같다.

2축 스틱으로 Steering 과 Accelerometer 를 제어하고 (채널1, 2), 스틱을 누르면 채널3 으로 디지털 입력을 받을 예정이다.

채널 4,5,6 중 채널 4는 아날로그 값을 Volume 으로 받고, 5,6 은 DIGITAL 로 받으려 한다. 마지막으로, V1.0 에서는 간단히 스틱의 입력값 범위를 설정하기 위한 Function S/W 를 하나 달아줄 것이다. 무쟈게 심플하다. Trim 이나 EPA 도 없다. 

전원은 집에있는 USB 보조배터리를 사용하도록 하고, 손잡이 부분에 넣도록 할 것이다.

기구는 집에있는 OC 마네킹 3D 프린터로 찍어볼것이다. 그런데 이게 도면 그리는게 쉽지 않을듯 하다.


자 일단 스틱을 붙였다. 인터넷으로 주문 가능한 바로 그 스틱이다. 뭐 얼마 하지도 않는다. VCC, GND, VRX, VRY, SW 이렇게 4선이 있다. 


나노에 연결하고 지난번 만들었던 코드를 수정했다.

송신기쪽 코드이다

큰 변화라면, 이전에 사용하던 TX_DATA 구조체 내에 accel, steering, ch3, ... 변수를 그냥 배열로 바꾸어 취급하기로 했다. 변수명을 하나씩 써주니 코드도 지저분해져서 배열로 만들고 Loop 로 돌려서 Analog 입력을 받아 저장하고 수신기 쪽으로 보낸다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * TX 에서 Steering(ch1), Acceleration(ch2), ch3, ch4, ch5, ch6 값을
 * 1000 (uS) ~ 2000(uS) 값으로 전달한다
*/
 
#include <SPI.h>
#include <RF24_config.h>
#include <RF24.h>
#include <nRF24L01.h>
#include "joon_nrf24l01_config.h"
#include "joon_transmitter_packet.h"
 
#define PIN_VRX     A0
#define PIN_VRY     A1
#define PIN_SW      2
 
#define IN_STEER    PIN_VRX
#define IN_ACCEL    PIN_VRY
#define IN_CH3      PIN_SW
#define IN_CH4      3
#define IN_CH5      4
#define IN_CH6      5
 
RF24 radio(PIN_CE, PIN_CSN);
TX_DATA tx;
unsigned long g_lStartTimeUs = 0;
 
int g_channels[] = { IN_STEER, IN_ACCEL, IN_CH3, IN_CH4, IN_CH5, IN_CH6 };
int g_analogChannels[] = { IN_STEER, IN_ACCEL };
 
void setup()
{
    Serial.begin(115200);
    while (!Serial);
    Serial.println("TX Serial Ready");
 
    // 기본 채널 76
    // 기본 D/R 1Mbps
    radio.begin();
    // 우선 아두이노의 핀 당 출력이 40mA 이고 전체 200mA 를 넘으면 불안해지므로
    // 일단 외부 전원 없이 사용하기 위해 LOW 모드로 세팅한다
    radio.setPALevel(RF24_PA_LOW);
 
    radio.openWritingPipe(TX_WRITE_CHANNEL);
    //radio.openReadingPipe(1,TX_READ_CHANNEL);
    //radio.startListening();
    for (int nChannelIndex = 0; nChannelIndex < sizeof(g_channels); nChannelIndex++)
        pinMode(g_analogChannels[nChannelIndex], INPUT);   
}
 
void loop()
{  
    g_lStartTimeUs = micros();
    // Transmitter 읽기
    readTransmitter(&tx);
 
    // 보내기
    if (!radio.write(&tx, sizeof(tx)))
        Serial.println("FAILED : TX Transmission failed");
 
    Serial.print("\n####### ");
    Serial.print(micros() - g_lStartTimeUs);
    Serial.println(" uS #######");
}
 
void readTransmitter(LPTX_DATA lpData)
{
    // Read Steering
    int val = analogRead(g_channels[0]);
    Serial.print("STEER : ");
    Serial.print(val);
    lpData->channel[0] = val;
     
    // Read Accel
    val = analogRead(g_channels[1]);
    Serial.print(" | ACCEL : ");
    Serial.print(val);
    lpData->channel[1] = val;
 
    // Read Ch3 ~ 6 Digital Pins
    for (int nChannelIndex = sizeof(g_analogChannels)/sizeof(int);
        nChannelIndex < sizeof(g_channels)/sizeof(int) ; nChannelIndex++)
    {
        val = digitalRead(g_channels[nChannelIndex]);
        Serial.print(" | CH");
        Serial.print(nChannelIndex+1);
        Serial.print(" : ");
        Serial.print(val);
        lpData->channel[nChannelIndex] = val;
    }
}

아래는 수신기쪽 코드이다

수신쪽 코드는 크게 변한것이 없고, 송신쪽에서 받은 배열값을 화면에 출력한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
 Name:      SX_RF24RX.ino
 Created:   10/30/2015 11:12:14 PM
 Author:    korean44
*/
 
// the setup function runs once when you press reset or power the board
#include <SPI.h>
#include <RF24_config.h>
#include <RF24.h>
#include <printf.h>
#include <nRF24L01.h>
#include "../joon_nrf24l01_config.h"
#include "../joon_transmitter_packet.h"
 
RF24 radio(PIN_CE, PIN_CSN);
TX_DATA data;
 
// 각 출력 채널의 출력 핀 번호 및 DIGITAL, ANALOG 타입 설정
CHANNEL g_outputChannelTypes[MAX_CHANNELS] =
{ {3,PIN_MODE::ANALOG} , {} };
 
void setup() {
    Serial.begin(115200);
    while (!Serial);
    Serial.println("RX Serial Ready");
 
    radio.begin();
    radio.setPALevel(RF24_PA_LOW);
    radio.openReadingPipe(1, RX_READ_CHANNEL);
    radio.startListening();
}
 
// the loop function runs over and over again until power down or reset
void loop() {
    unsigned long start_wait_us = micros();
    bool timeout = false;
    while (!radio.available()) {
        if (micros() - start_wait_us > RF24_TIMEOUT_US) {
            timeout = true;
            Serial.println("--TIMEOUT--");
            break;
        }
    }
     
    if (!timeout) {
        radio.read(&data, sizeof(data));
        unsigned long read_time_us = micros();
         
        Serial.print("Steering : ");
        Serial.print(data.channel[0]);
        Serial.print("/ Accel : ");
        Serial.print(data.channel[1]);
        Serial.print("/ CH3 : ");
        Serial.print(data.channel[2]);
        Serial.print("/ CH4 : ");
        Serial.print(data.channel[3]);
        Serial.print("/ CH5 : ");
        Serial.print(data.channel[4]);
        Serial.print("/ CH6 : ");
        Serial.println(data.channel[5]);
        Serial.print("== Receive Delay : ");
        Serial.print(read_time_us - start_wait_us);
        Serial.println(" uS");
    }
}



그런데 이상한 현상이 발생한다. Transmission Fail 이 계속 떨어지고, 전송 속도가 무려 40ms 정도가 걸린다. 뭔가 특이한것도 없는데 이렇다.. 혹시 콘덴서 안달아서 이러는가 싶기도 하지만 PA Level 을 LOW 로 주었는데도 이런거면 큰일이다.. 우선 값이 전달되는건 되는걸 확인하고 일단 닫았다.


다음날 저녁에 퇴근하고 집에와서 애들 자는거 보고 또 열었다. 그리고 원래 있던 코드를 손도 안대고 돌려본다. 그런데 갑자기 FAIL 이 안뜬다.. 뭐 이런경우가.. 어제 저녁에는 100% 오류가 나더니.. (기분탓인가.. 그러기에는 저렇게 확연한 증거가 있는데..)

아무튼, 이쯤 하고 값이 잘 전달된다는걸 확인했으니 다시 프로젝트를 닫았다. 참 이상한일이다.

브래드보드에서 실제 기구에 이식할때에는 꼭 콘덴서 달아주리라 마음먹고 오늘은 이쯤한다.

다음에는 출력쪽을 다루어야 하고, 회로도도 그려서 올려야겠다.

지금까지의 회로도는 아래와 같다



반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,