Posted by 살레시오
,
Posted by 살레시오
,
Posted by 살레시오
,
Posted by 살레시오
,

  아두이노에서는 기본적으로 printf()함수를 지원하지 않는데 그 기능이 아쉬울 때가 있다. 그런데 다음과 같이 vsprintf() 와 vsnprintf() 함수를 이용하면 쉽게 printf() 기능을 구현할 수 있다. 아두이노 setup()함수 위에 다음과 같이 _printf()함수를 정의한다.


#include <stdio.h>

#include <stdarg.h>


void _printf(const char *s, ...){

   va_list args;

   va_start(args, s);

   int n = vsnprintf(NULL, 0, s, args);//문자열 길이를 먼저 구함

   char *str = new char[n+1]; //메모리 할당

   vsprintf(str, s, args);//실제 내용을 복사

   va_end(args);

   Serial.print(str);

   delete [] str; //메모리 해제

}


그런데 이렇게만 하면 _printf() 함수 내에서 실수를 표시하는 서식문자 %f, %g, %e를  사용할 수 없다는 문제가 있다. 이 문제를 해결하려면 다음 파일을 열어서 수정해야 한다.


{아두이노 설치 폴더}\hardware\arduino\avr\platform.txt

윈도우의 경우 C:\Program Files\Arduino\hardware\arduino\avr\platform.txt


이 파일에서 다음 줄을 찾아서


compiler.c.elf.extra_flags=


다음과 같이 끝에 추가한다.


compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt -lm


이제 아두이노 IDE를 다시 실행하면 된다. 전체 프로그램은 다음과 같다.


#include <stdio.h>

#include <stdarg.h>


void _printf(const char *s,...){

   va_list args;

   va_start(args, s);

     int n = vsnprintf(NULL, 0, s, args);

     char *str = new char[n+1];

     vsprintf(str, s, args);

   va_end(args);

   Serial.print(str);

   delete [] str;

}


void setup() {

 Serial.begin(9600);

 _printf("%d+%d=%d\n",1,2,3);

 _printf("float var %.4f\n",1.234);

 _printf("hello %s\n", "world");

}


void loop() {

}


시리얼 모니터를 통해서 볼 수 있는 실행 결과는 다음과 같다.


1+2=3

float var 1.2340

hello world


 한 가지 더 지적할 것은 아두이노에서는 문자열 상수를 전역변수로 저장하기 때문에 RAM을 차지한다. 그러니까 위의 프로그램에서 그냥 큰따옴표로 묶인 문자열들은 전부 램에 저장된다. 램용량이 많지 않은 아두이노에서는 문자열 상수는 보통 F() 매크로로 플래시메모리 영역에 저장하여 RAM을 아낄 수 있다. 위의 _printf() 함수의 첫 번째 인자를 F()매크로로 저장한 문자열로 받을 수 있도록 수정하려면 내부에서 vsnprintf()함수 대신 vsnprintf_P()을, 그리고 vsprintf()함수 대신 vsprintf_P()함수를 사용해야 하는데 다음과 같다.


#include <stdio.h>

#include <stdarg.h>


void _printf(const __FlashStringHelper *s, ...){

   va_list args;

   va_start(args, s);

     int n = vsnprintf_P(NULL, 0, (const char*)s, args);

     char *str = new char[n];

     vsprintf_P(str, (const char*)s, args);

   va_end(args);

   Serial.print(str);

   delete [] str;

}


void setup() {

 Serial.begin(9600);

 

 _printf(F("%d+%d=%d\n"),1,2,3);

 _printf(F("float var %.4f\n"),1.234);

 _printf(F("hello %S\n"), F("world"));

}


void loop() {

}


서식문자열 내부에서 플래시 문자열을 표시하려면 대문자 S를 사용한 ‘%S’ 서식문자를 사용해야 한다는 것에 유의하자. 실행 결과는 앞의 경우와 동일하다.



Posted by 살레시오
,

  Visual Stdudio Code(VSC)에 PlatformIO 플러그인을 깔고 아두이노 우노에 프로그램을 업로드해 보았다. (Atom에디터에도 플러그인이 있는데 Clang을 추가로 설치해 주어야 해서 설치 편의성은 VSC가 더 낫다.) 자동완성이 지원되는 등 VSC자체가 뛰어난 에디터이다 보니 개발 편의성은 높다.


  하지만 아두이노IDE로 프로그램할 때와 달리 c++ 문법을 strict하게 지켜야 한다.


#include <Arduino.h>

void blink();

void setup() {
// put your setup code here, to run once:
pinMode(13,OUTPUT);
}

void loop() {
blink();
}

void blink() {
digitalWrite(13,HIGH);
delay(100);
digitalWrite(13,LOW);
delay(100);
}


프로그램명도 main.cpp이다.(ino파일이 아님.) 위와 같이 Arduino.h를 명시적으로 인클루드시켜야 한다던지 함수의 선언도 반드시 해줘야 한다.


  컴파일은 문제 없고 업로드도 자동으로 우노가 연결된 포트를 인식해서 수행되었다.

Posted by 살레시오
,
Posted by 살레시오
,
Posted by 살레시오
,
Posted by 살레시오
,
7세그먼트, 이차원 배열, analogReference()함수 등
Posted by 살레시오
,