안녕하세요, 라즈베이 파이를 이용해 CM700을 제어하려는 학생입니다.

 

로보플러스를 이용해 지그비 리모콘 U를 누르면 다이나믹셀 목표위치를 0으로, D를 누르면 1024로, 떼면 512로 이동하는 간단한 테스크를 짜서 동작을 확인했습니다.

물론 현재 지그비 리모콘으로는 매우 잘 작동하며, 제 목표는 라즈베리파이의 GPIO 출력핀, 또는 LN101 USB를 통해 CM700과 UART 통신을 통해 리모콘을 모방하는 것입니다.

현재 간단하게 아두이노로 시리얼통신을 테스트중인데요, 통신 패킷이 잘 이해가 가지 않습니다.

지그비 SDK를 살펴본 결과,

int zgb_tx_data(int data)
{
    unsigned char SndPacket[6];
    unsigned short word = (unsigned short)data;
    unsigned char lowbyte = (unsigned char)(word & 0xff);
    unsigned char highbyte = (unsigned char)((word >> 8) & 0xff);

    SndPacket[0] = 0xff;
    SndPacket[1] = 0x55;
    SndPacket[2] = lowbyte;
    SndPacket[3] = ~lowbyte;
    SndPacket[4] = highbyte;
    SndPacket[5] = ~highbyte;

    if( zgb_hal_tx( SndPacket, 6 ) != 6 )
        return 0;

    return 1;
}

에서, 즉, int data로 입력받은 정수를 16진수화시켜 6바이트 통신 패킷에 맞게 변환시키는 것 까지는 이해했습니다. 

이때, unsigned char을 사용하는데, 즉, 통신패킷에 맞게 변환된 값은 char 형태로 저장되는 건가요?

통신 패킷으로 전달하는 데이터가 char인지, int인지, int면 보낼때 DEC로 보내야 하는지, HEX로 보내야 하는지 잘 모르겠습니다.

또 SndPAcket[6]이라는, 일종의 문자열인데 한번에 string으로 전달하는 것인지, 순차적으로 하나하나 전달하는 것인지 궁금합니다.

 

현재 아두이노 상에서 for문을 사용해 순차적으로 명령을 내리는 것을 테스트해 보았습니다. SDK에서 위 함수 전환 부분만 copy하여 포인터 관련 부분은 지워버리고, SndPacket을 전역변수로 바꾸어 테스트 했습니다. 

unsigned char SndPacket[6];

int zgb_tx_data(int data)
{
    //unsigned char SndPacket[6];
    unsigned short word = (unsigned short)data;
    unsigned char lowbyte = (unsigned char)(word & 0xff);
    unsigned char highbyte = (unsigned char)((word >> 8) & 0xff);

    SndPacket[0] = 0xff;
    SndPacket[1] = 0x55;
    SndPacket[2] = lowbyte;
    SndPacket[3] = ~lowbyte;
    SndPacket[4] = highbyte;
    SndPacket[5] = ~highbyte;

    //if( zgb_hal_tx( SndPacket, 6 ) != 6 )
        return 0;

    //return 1;
}

int t=0;

zgb_tx_data(t);
   
for(int m=1; m<=6; m++)
{
   Serial.print(SndPacket[m],HEX);// Serial.println("thtest");
 }

위 소스를 이용해 tx,rx를 크로스해 CM700에 입력해본 결과, 제어기의 RX LED가 깜빡이는건 확인했습니다만 모터는 작동하지 않더군요. 

 

CM700 제어기에 명령을 전달할때, 통신 패킷에 따라 어떻게 전달해야 하는지 궁금합니다.

결론적으로,

1. 명령의 자료형(int,char)은 무엇인지, 전달할때 DEC인지 HEX인지,

2. 위처럼 for문을 사용해서 6개의 데이터를 순차적으로 전달해야 하는지,

3. 아니면 SndPAcket[6]이라는, 일종의 문자열을 한번에 string으로 전달하는 것인지,아니면 또 다른 방법이 필요한지 알려주시면 감사드리겠습니다.

 

두서없이 질문드려 죄송합니다. 많은 조언 부탁드립니다.

블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

OLED 디스플레이 사용을 위해 필요한 라이브러리와 소스코드를 정리했습니다. 먼저 확인해야 할 것은 OLED 디스플레이의 드라이버 칩입니다. 드라이버 칩에 따라 라이브러리와 사용방법이 완전히 틀려집니다.

 

Adafruit 그래픽 라이브러리 (SSD 1306 및 일부 TFT LCD 등…)

일반적으로 많이 사용.  Adafruit 에서 제작한 라이브러리를 사용하거나 좀 더 원시적인 코드로 구동이 가능합니다. Adafruit 라이브러리는 각종 도형 및 폰트, 선, 채우기 함수를 제공하는 대신 그래픽 버퍼로 램을 꽤 많이 잡아 먹습니다.  아두이노가 보통 2KByte 램으로 돌아간다는 점을 생각하면 램이 부족한 경우가 생길 수 있습니다. 램이 부족할 경우 각종 변수값이 이상하게 입력되고 화면이 찢어지는(?) 현상이 발생합니다.

Adafruit 라이브러리는 2개로 구성되어 있습니다. GFX 라이브러리가 공통된 drawing 함수를 제공하고, 드라이버 칩에 따라 적절하게 동작하도록 드라이버 라이브러리가 맞물리도록 되어 있습니다.

==> OLED + Adafruit 라이브러리 사용방법 페이지

Adafruit OLED 모듈 및 라이브러리 사용법, Adafruit 라이브러리와 호환 가능한 디스플레이 및 드라이버 칩

SSD1306 칩 드라이버 직접 제어하는 방법 예제코드

 

u8glib 범용 그래픽 라이브러리

SSD1325, ST7565, ST7920, UC1608, UC1610, UC1701, PCD8544, PCF8812, KS0108, LC7981, SBN1661, SSD1306, T6963 등을 지원하는 범용 그래픽 드라이버로 u8glib 라이브러리가 있습니다. 8비트 마이크로 컨트롤러에서 사용할 수 있는 가장 막강한 라이브러리입니다. 화면 업데이트가 조금 느린대신 램을 적게 차지하고 안정적입니다.

==> 상세한 사용법 매뉴얼이 업데이트 되었습니다!! 링크로 확인하세요.

라이브러리 공식 페이지지원하는 디바이스 목록, 매뉴얼 및 예제 코드

 

 Character LCD, MGLCD, UTFT 라이브러리

위에서 적합한 라이브러리가 없는 경우 아래 링크를 확인하세요. 각종 LCD 및 UTFT 를 지원하는 라이브러리입니다.

http://www.henningkarlsen.com/electronics/library.php?id=51

 

GLCD 라이브러리

흔한건 아니지만.. KS0108 controller chip 기반한 LCD는 아래 링크로…

http://www.pjrc.com/teensy/td_libs_GLCD.html

OpenGLCD 라이브러리 프로젝트가 있습니다. 여기 라이브러리 주목할만 합니다.

https://bitbucket.org/bperrybap/openglcd/wiki/Home

 

SH1106 라이브러리

SSD1306과 비슷하지만 별도의 라이브러리가 필요한 것 같습니다. 아래 링크를 참고하세요.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=1150108

아래 라이브러리가 쓸만하다고 하네요.

https://github.com/stanleyhuangyc/MultiLCD

Wonho 님 께서 SH1106 칩셋용 Adafruit 라이브러리를 만들어서 공유중입니다. 아래 링크에 가시면 라이브러리를 받으실 수 있습니다.

https://github.com/wonho-maker/Adafruit_SH1106

 

wonho-maker/Adafruit_SH1106

Adafruit graphic library for SH1106 dirver lcds. Contribute to wonho-maker/Adafruit_SH1106 development by creating an account on GitHub.

github.com

 

 

그래픽 램의 용량 (2K) 때문에 Library 들 간에 Collision 으로 보이는 현상들이 발생했다.

Compatiblity Check 를 해본 결과

 

LiquidCrystal 과 Adafruit 간에 문제가 있는 것으로 생각을 했는데

LiquidCrystal_i2C는 LiquidCrystal을 SPI 용도로 제작한 것에서 i2c 방식으로 포팅을 해서 만든 개수 라이브러리 였고

사실상 Adafruit LiquidCrystal 을 기반해서 만들어졌기 때문에 별 문제가 없었던 것이다.

 

오히려 문제가 됬었던 것은 TM1637 FND Library 였는데 

내부 클래스에서 선언하는 방식과 사용하는 방식이 굉장히 비슷한 데다가 

 

일반적인 example 들이 display 로 생성자를 이용하여 사용하는 것을 볼 때, 메모리 간에 근접문제가 있었던 것이 아닌가 싶다.

 

일단 중요한 것은, 반드시 필요없는 라이브러리나 헤더를 추가하지 않는 것에 유의를 해야할 것 같다.

(특히나 용량이 60~70% 이상으로 올라가면 안정성이 떨어져 제대로 동작하지 않을 가능성이 추가적으로 늘어난다.)

 

블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

LiquidCrystal and Adafruit SSD1306(SSH1102) Collison Detected

- Library Collision, may be not distingsh between two I2C Sensors, LCD and OLED.

 

Trouble Shooting Processing Start..

블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

[Time]

설명

매개변수에 지정된 시간(마이크로 초)동안 프로그램을 멈춘다. 1밀리초는 1000 마이크로 초, 1초는 100만 마이크로 초. 현재, 정확한 delay를 만드는 가장 큰 값은 16383. 미래의 아두이노 릴리스에서 바뀔 수 있다. delay 가 몇 천 마이크로 초 보다 길면, 대신 delay() 를 써야 한다.

문법

delayMicroseconds(us)

매개변수

us: 멈출 마이크로 초 (unsigned int)

반환

없음

예제 코드

이 코드는 핀번호 8이 출력 핀으로 동작하도록 구성한다. 약 100 마이크로 초의 펄스 열을 보낸다. 근사값은 코드에서 다른 명령 실행으로 인한 것이다.

 

int outPin = 8;               // 디지털 핀 8

void setup() {
  pinMode(outPin, OUTPUT);    // 디지털 핀을 출력으로
}

void loop() {
  digitalWrite(outPin, HIGH); // 핀을 켠다
  delayMicroseconds(50);      // 50 마이크로 초 쉰다
  digitalWrite(outPin, LOW);  // 핀을 끈다
  delayMicroseconds(50);      // 50 마이크로 초 쉰다
}

주의와 경고

이 함수는 3 마이크로 초 이상 범위에서 매우 정확하게 돌아간다. delayMicroseconds 가 작은 지연시간동안 정확히 수행한다고 보장할 수 없다. 아두이노 0018 현재, delayMicroseconds() 는 더이상 인터럽트를 비활성화 하지 않는다.

블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

아두이노의 Serial.write() 함수는  Serial 포트에 하나의 바이트 또는 그 이상의 바이트를 전송하는데 사용합니다. 주로 데이터 통신을 구현할 때 사용되며 Serial.print() 함수와 구분되어 사용합니다.

Serial.write() 함수는 숫자를 전송할 때 숫자 있는 그대로 전송합니다. 이는 숫자를 ASCII 코드로 변환하여 전송하는 Serial.print() 함수와 구분되며 일부 매개변수 입력에도 차이가 있습니다.

 

Serial.write()

 

Serial.write(val);
Serial.write(str);
Serial.write(buf, len);

매개변수(Parameters)
val : 1 바이트 데이터(0x00 ~ 0xFF)
str : 문자열(ex ‘A’, “Hello”)
buf : byte형 배열에 저장된 데이터, len 만큼 바이트 전송

반환값(Return)
size_t: write() : 전송한 byte 수

 

 

byte buff[10] = { 64, 'A', 0x42, 67, 68, 69, 70, 71, 72, 73};
 
void setup() {
  Serial.begin(115200);
}
 
void loop() {
  Serial.write(64);
  Serial.write("abc");
  Serial.write(buff, 5);
  Serial.println(" ");
  delay(1000);
}

위 예제를 아두이노 보드에 업로드하고 시리얼 모니터로 실행 결과를 보면 “@abc$ABCD” 이 반복적으로 출력될 것입니다.

하나씩 살펴보면

시리얼 모니터에서 수신된 <64>를 ASCII 값으로 판단하고 이에 해당하는 문자 ‘@’을 출력합니다. 문자열은 그대로 출력하여 “abc”가 이어서 출력되고 byte형 배열 중 5개의 데이터는 숫자는 ASCII 문자로, 문자는 문자로 출력합니다.

<64> → ‘@’
“abc” → “abc”
<36> → ‘$’
‘A’ → ‘A’
<0x42> → ‘B’
<67> → ‘C’
<68> → ‘D’

 

참고

아두이노 시리얼 모니터는 수신된 데이터를 ASCII 코드의 문자로 변화하여 출력합니다.  raw 데이터를 확인하기 위해서는 헥사(16진수) 값 등을 확인할 수 있는 별도의 시리얼 모니터 프로그램을 사용하셔야 합니다.

'홍익인간 프로젝트 > Arduino C' 카테고리의 다른 글

LiquidCrystal and Adafruit SSD1306(SSH1102) Collison  (0) 2021.03.19
delayMicroseconds()  (0) 2021.03.11
[아두이노 레퍼런스] Serial.write() 함수  (0) 2021.01.31
pulseIn() Function  (0) 2021.01.22
pinMode() Function  (0) 2021.01.22
What's means F() function ?  (0) 2021.01.14
블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

[Advanced I/O]

Description

Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go from LOW to HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds or gives up and returns 0 if no complete pulse was received within the timeout.

The timing of this function has been determined empirically and will probably show errors in longer pulses. Works on pulses from 10 microseconds to 3 minutes in length.

Syntax

pulseIn(pin, value)
pulseIn(pin, value, timeout)

Parameters

pin: the number of the Arduino pin on which you want to read the pulse. Allowed data types: int.
value: type of pulse to read: either HIGH or LOW. Allowed data types: int.
timeout (optional): the number of microseconds to wait for the pulse to start; default is one second. Allowed data types: unsigned long.

Returns

The length of the pulse (in microseconds) or 0 if no pulse started before the timeout. Data type: unsigned long.

Example Code

The example prints the time duration of a pulse on pin 7.

int pin = 7;
unsigned long duration;

void setup() {
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop() {
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
}

'홍익인간 프로젝트 > Arduino C' 카테고리의 다른 글

delayMicroseconds()  (0) 2021.03.11
[아두이노 레퍼런스] Serial.write() 함수  (0) 2021.01.31
pulseIn() Function  (0) 2021.01.22
pinMode() Function  (0) 2021.01.22
What's means F() function ?  (0) 2021.01.14
u8g2setupcpp  (0) 2020.12.25
블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

[Digital I/O]

Description

Configures the specified pin to behave either as an input or an output. See the Digital Pins page for details on the functionality of the pins.

As of Arduino 1.0.1, it is possible to enable the internal pullup resistors with the mode INPUT_PULLUP. Additionally, the INPUT mode explicitly disables the internal pullups.

Syntax

pinMode(pin, mode)

Parameters

pin: the Arduino pin number to set the mode of.
mode: INPUT, OUTPUT, or INPUT_PULLUP. See the Digital Pins page for a more complete description of the functionality.

Returns

Nothing

Example Code

void setup() {
  pinMode(13, OUTPUT);    // sets the digital pin 13 as output
}

void loop() {
  digitalWrite(13, HIGH); // sets the digital pin 13 on
  delay(1000);            // waits for a second
  digitalWrite(13, LOW);  // sets the digital pin 13 off
  delay(1000);            // waits for a second
}

Notes and Warnings

The analog input pins can be used as digital pins, referred to as A0, A1, etc.

See also

블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요

Serial.print(F(“Hello World”));

Oct 06, 2016, 03:38 pm

I found this comment on Serial.print:

You can pass flash-memory based strings to Serial.print() by wrapping them with F(). For example :

Serial.print(F("Hello World"))

What does it mean to pass flash-memory based strings?

 

 

Re: Serial.print(F(“Hello World”));

#1

Oct 06, 2016, 03:39 pm

It means the string isn't using up RAM.

 

 

 

Re: Serial.print(F(“Hello World”));

#2

Oct 06, 2016, 03:59 pm

When you compile your program it says how much program memory (stored in flash) you are using and how much dynamic ram you are using.

If you use F() you can move constant strings to the program memory instead of the ram. This will take up space that will decrease the amount of other code you can write. But it will free up dynamic ram.

My chip has 32KB of Flash memory (2Kb taken up by bootloader) and 2KB or RAM. Sometimes I need to store lots of data in RAM so I move the constant strings to Flash memory. Sometimes my program has a lot of steps and I have a shortage of Flash memory so I leave the strings in RAM.

mrburnette

 

 

 

 

#3

Oct 06, 2016, 07:52 pm Last Edit: Oct 06, 2016, 07:55 pm by mrburnette

Quote

If you use F() you can move constant strings to the program memory instead of the ram.

Actually what happens in a Harvard architecture uC is that the compiled string stays in flash and does not get copied to SRAM during the C++ initialization that happens before your sketch receives run control.

Since the string is not moved to SRAM, it has the PROGMEM property and runs from flash.

 

 

Re: Serial.print(F(“Hello World”));

#4

Oct 06, 2016, 08:08 pm

Quote from: CaverAdam on Oct 06, 2016, 03:59 pm

Sometimes my program has a lot of steps and I have a shortage of Flash memory so I leave the strings in RAM.

That's not how it works.

Your string constants are ALWAYS in flash memory. They have to be, because when you take power away from RAM everything's gone. When you put power back on again, they have to be reloaded from somewhere, and that somewhere is the flash memory. Leaving off PROGMEM will do nothing to save you significant amounts of flash memory.

It's just that a normal part of initializing a C++ program is to load those arrays into SRAM before setup(). PROGMEM is an AVR-specific attribute that can be applied to variables that tells the compiler to not do that. Because flash is in a different memory space than RAM, special functions are needed to access from flash than from RAM.

Hackaday: https://hackaday.io/MarkRD
Advanced C++ Techniques: https://forum.arduino.cc/index.php?topic=493075.0

'홍익인간 프로젝트 > Arduino C' 카테고리의 다른 글

pulseIn() Function  (0) 2021.01.22
pinMode() Function  (0) 2021.01.22
What's means F() function ?  (0) 2021.01.14
u8g2setupcpp  (0) 2020.12.25
PCF8574 I2C 확장보드로 CLCD, Text(텍스트) LCD 구동 (아두이노)  (0) 2020.12.25
LiquidCrystal I2C - 3 Arguments Type  (0) 2020.12.25
블로그 이미지

remoted

Remoted's IT LAB & POST DATABASE

댓글을 달아 주세요