스케치를 실제로 축소하는 방법


9

테스트 목적으로 가능한 한 작은 스케치를 만들고 싶습니다. 문제는 빈 설정과 루프로 BareMinimum 스케치를 컴파일 할 때 Uno의 경우 466 바이트, Leonardo의 경우 4,242 바이트입니다. 추가 기능이없는 자체 코드를 작성할 수있는 방법이 있습니까 (즉, Timer0 for millis()delay()). 또한 Leonardo의 키보드 / 마우스 기능을 비활성화하고 싶습니다.


4
이 태그를 레오나르도 태그로 표시하고 uno가 아니라 (한 보드에 중점을 두어야) 안됩니까? 이들은 별도의 질문입니다.
asheeshr

빈 보드 컴파일 스케치는 많은 보드, 특히 기본 USB 기반 보드에
적합

또한 Leonardo의 키보드 / 마우스 기능을 비활성화하고 싶습니다. 두 번째 질문입니다.
asheeshr

답변:


3

https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification에 따라 사용자 정의 boards.txt 파일을 사용하여 자체 보드 정의를 작성할 수 있어야합니다 . 내가 알다시피 leonardo의 정의에는 몇 가지 USB 기능이 있습니다. 4K의 컴파일 포함은 프로세서 유형이 아닌 이러한 플래그를 기반으로하기를 바랍니다.

boards.txt가 업로드를 사용하는 경우 Leonardo의 부트 로더 섹션과 uno의 빌드입니다.

이것은 핵심 라이브러리 빌드가 프로세서 특정 플래그를 사용하여 USB 기능을 포함하지 않는다고 가정합니다.

그런 일을하면. 다시 게시, 나는 다른 사람들이 그런 관심이있을 것이라고 확신합니다.


최근에 실제로 UNO를 최대한 활용하고

#if !defined(__AVR_ATmega32U4__)
...

레오나르도에 맞게 스케치에 많은 추가 기능이 있습니다.

나는이 4K가 Leo의 USB CDC를 통해 Serial.print를 포함했기 때문에 (잘못) 가정했다. 그러나 빈 스케치의 메모리 덤프 후에도 여전히 존재합니다.

C:\Users\mflaga\AppData\Local\Temp\build8958339595868119500.tmp>avr-objdump -d sketch_feb13a.cpp.elf > sketch_feb13a.cpp.elf.lst

말이됩니다. Leonardo는 원격 재부팅을 치기 위해 AVR-DUDE에서 1200 Baud 연결을 감지하기 위해 여전히 USB-CDC 클라이언트 (4K)를 필요로합니다.


따라서 빌드에서 USB없이 사용자 정의 boards.txt를 만들려면

leonardo.upload.use_1200bps_touch=true

제거되었습니다.

대상에 일단로드되면 업로드를 대상의 수동 재설정과 동기화해야합니다. 원격 재부팅 기능이 손실됩니다.


Serial.print를 생략하더라도 4K가 여전히 컴파일되는 이유에 대해 업데이트되었습니다.
mpflaga

3

나는 최근에 이것을 정확하게하고 싶었다. 그렇게 할 수있는 좋은 방법이 없기 때문에 Stino sublime-text arduino 플러그인이 정확히 이것을 수행 하는 패치작성했습니다 . 이후에 승인되었으므로 최신 Stino 설치에 있어야합니다.

이것은 Stino에 새로운 옵션을 추가합니다 :

여기에 이미지 설명을 입력하십시오

이 모드를 사용하면 다음과 같은 컴파일 결과가 생성됩니다.

우노의 경우 :

이진 스케치 크기 : 172 바이트 (최대 32256 바이트, 0.53 %)
예상 메모리 사용 : 0 바이트 (최대 1024 바이트, 0.00 %)

레오나르도

이진 스케치 크기 : 240 바이트 (최대 28672 바이트, 0.84 %)
예상 메모리 사용 : 0 바이트 (최대 2560 바이트, 0.00 %)

실제로 컴파일 된 출력으로 leonardo를 프로그래밍 하는 것은 아마도 자동 재설정 기능을 중단 할 있기 때문에 좋지 않은 생각 일 있지만 원한다면 할 수 있습니다. 그의 답변에 이것을 지적 해 주신 mpflaga의 햇팁.

메모리 보고서는 실제로 올바르지 않지만 별도의 문제 입니다.

위의 코드는 다음과 같습니다.

int main()
{
    while (1)
    {

    }
}

몇 가지 참고 사항 :

  • 당신은 당신이 이제까지 실제로하지 않는 것이, 더 이상 "스케치"를 작성되지 않는 스케치를 작성합니다. 당신은 프로그램을 작성 합니다 . 기간. 나는 Arduino wackos가 말하고 싶은 것을 신경 쓰지 않고 용어를 재정의하지 않습니다.
  • 모든 인터럽트 관리는 수동입니다. 이것은 아니 milis()거나 비슷한 것을 의미 합니다.
  • 원하는 경우 여전히 arduino 직렬 라이브러리 등을 사용할 수 있습니다 . 당신은해야합니다 #include <Arduino.h>.
  • 을 정의 main합니다. 에서 돌아 오지 않습니다 main. 설정 항목을 원하면 while (1).

@jfpoilpret IDE라고 부릅니까? 매크로가있는 메모장과 비슷합니다 ...
Ron

@ Ron-E 나는 그것을 IDE라고 부르지 않는다. Arduino IDE 는 그 이름이기 때문에 그 이름을 쓸 가치가 없지만 그 이름을 사용했다.
jfpoilpret

2
@FakeName Stack Exchange 사이트에서는 잘못된 언어를 사용할 수 없습니다 ( stackoverflow.com/help/behavior 참조 ). 이 경우에는 수정했지만 앞으로이 사이트에서 expletives를 사용하지 마십시오. 감사.
Peter Bloomfield

2

스케치에 따라 다르지만 메소드와 함께 코드를 재사용 하여 크기를 다소 줄일 수 있습니다 .

이 코드를 보자 :

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  val = digitalRead(10);
}

Arduino Uno에서 1,322 바이트 이제 조금 줄이자 :

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  for(uint8_t i = 0; i < 8; i++) {
    blink(HIGH);
    blink(LOW);
  }    
  val = digitalRead(10);
}

void blink(uint8_t state) {
  digitalWrite(led, state);   // turn the LED to the right state
  delay(1000);                // wait for a second
}

1,194 바이트 약 10 % 감소합니다!

어쨌든 스케치를 크게 축소 하지는 않지만 한계를 초과하는 2 바이트이거나 기능을 잃지 않고 시작하기 위해 더 작은 스케치를 만들고 싶을 때 가장 쉬운 경로 일 수 있습니다. 모든 상황에 적용되는 것은 아니지만 때때로 유용합니다.


일반적으로 코드를 함수로 가져 오면 컴파일러는 어려운 작업을 수행하고 나머지는 자동으로 수행합니다.
Cybergibbons

@Cybergibbons [정말 익숙하지 않은 사용자를 위해] 정의 할 수 있습니까?
Anonymous Penguin

3
코드를 함수로 나누고 효율적이지 않은 경우 일반적으로 컴파일러가 코드를 인라인합니다. 그러나 컴파일러는 코드를 함수로 분리하지 않습니다. 따라서 더 많은 함수를 작성하는 것이 거의 항상 좋습니다.
Cybergibbons

1
또한 코드를 함수에 추가하면 훨씬 더 쉽게 읽고 이해할 수 있습니다

직접 포트 액세스를 사용하면 크기가 646 바이트로 줄어 듭니다. avr-libc (Arduino 코어 없음) 만 사용하면 220 바이트까지 줄어 듭니다.
Edgar Bonet 2016 년

0

@annonomus 펭귄, 우리가 할 수있는 확실한 코드는 컴퓨터에서 우노를 위해 1180 바이트 플래시 + 13 바이트 RAM으로 컴파일되지만 개선 할 수 있습니다 :) 그래서 골프 도전과 우리가 사업을하고 있기 때문에 유용한 팁 배우기.

1 단계 : 변수 요구 사항을 줄입니다. led 포트에 int를 사용하는 것은 약간 과도하게 보일 것입니다. 우리는 arduino에 65535 개의 주소 지정 가능한 IO 포트가 없습니다 :) 그래서 우리는 재미를 위해 바이트로 변경합니다. 나중에 #define으로 변경하지만 너무 큰 변수 유형을 사용할 때의 영향을 보여줍니다.

byte led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

1172 바이트 + 13 바이트 RAM으로 컴파일합니다. 이것은 정수 대신 바이트에 필요한 조작이 적기 때문에 8 바이트의 플래시를 절약합니다. 나는 12 바이트의 램을 기대하지만 괜찮습니다. 그렇게 많지는 않지만 저장된 모든 바이트가 좋습니다.

2 단계 : 변수를 의미있는 시점으로 정의로 전환 예를 들어, led 바이트는 필요하지 않으며 핀 자체는 풀리지 않습니다.

#define LED 13
int val;

void setup() {                
  pinMode(LED, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

1142 바이트 플래시 + 11 바이트 램으로 컴파일합니다. 이미 38 바이트가 저장되었습니다. 이것은 int 값을 페치하는 데 필요한 레지스터 조작이 적기 때문입니다. 또한 RAM에서 2 바이트를 저장했습니다. (아직 바이트가 왜 1 바이트 미만의 램으로 컴파일되지 않았는지 궁금합니다 .....)

3 단계 : 코드 최적화 두 가지 지연이 있습니다. 1 지연으로 변경하면 공간을 절약 할 수 있는지 궁금하지만 LED 핀의 값을 알아 내고 토글 (반전)해야합니다. 우리는 digitalRead ()로 그렇게 할 수 있지만 공간을 절약 할 수 있습니까?

#define LED 13
int val;
void setup() {                
  pinMode(LED, OUTPUT);     
}
void loop() {
  blink();
  val = digitalRead(10);
}
void blink() {
  digitalWrite(LED, !digitalRead(LED));   // toggle the led based on read value
  delay(1000);               // wait for a second and spare yourself the other delay
}

1134 바이트 + 11 바이트 램으로 컴파일합니다. 예이! 다른 8 바이트. 이는 총 46 바이트와 2 줄의 코드 줄입니다.

코드 크기를 줄이는 또 다른 일반적인 팁. String 클래스를 사용하지 마십시오. char 배열, strcpy (), strcmp ()를 다루는 방법을 배우십시오. 기본 문자열 작업이 모두 있다면 String 클래스의 사용은 대부분 플래시와 RAM 모두에서 공간을 낭비하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.