Как сократить код?

tagir000
Offline
Зарегистрирован: 11.06.2015

Имеется код (мигание светодиода по типу сердца:

int i;
int LED = 10;

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

void loop() {
       
  for (i = 50; i < 255; i=i+15) {
   analogWrite(LED,i);
   delay(50);
  }

    
 for (i=255; i > 80; i=i-30) {
   analogWrite(LED,i);
   delay(50);
  }
 
 
   for (i=80; i < 255; i=i+15) {
   analogWrite(LED,i);
   delay(50);
  }
  
 
 for (i=255; i > 50; i=i-10) {
   analogWrite(LED,i);
   delay(50);
  }
  
  
   delay(300);
  
}

 

Писал в меру своих знаний, хочу узнать можно ли написать его еще короче?

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Поделить на ноль?

tagir000
Offline
Зарегистрирован: 11.06.2015

Puhlyaviy пишет:
Поделить на ноль?

других вариантов нет?))

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

tagir000 пишет:

Puhlyaviy пишет:
Поделить на ноль?

других вариантов нет?))


А зачем?

tagir000
Offline
Зарегистрирован: 11.06.2015

Puhlyaviy пишет:
 А зачем?

Ради спортивного интереса. Я только учусь, потому хотелось бы знать)

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

tagir000 пишет:

Puhlyaviy пишет:
 А зачем?

Ради спортивного интереса. Я только учусь, потому хотелось бы знать)


Ну тогда гребите в сторону ассемблера.

tagir000
Offline
Зарегистрирован: 11.06.2015

Puhlyaviy пишет:
tagir000 пишет:

Puhlyaviy пишет:
 А зачем?

Ради спортивного интереса. Я только учусь, потому хотелось бы знать)

Ну тогда гребите в сторону ассемблера.

 

Все короче ясно с вами тут. Другого ответа и не ожидал услышать

nevkon
Offline
Зарегистрирован: 20.01.2015

Сократить код можно, но памяти он будет поедать больше и будет более неповоротливый и сложный для прочтения.

maksim
Offline
Зарегистрирован: 12.02.2012

Почитайте Функции

const int LED = 10;

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

void loop() {
  Func(50, 255, 15);
  Func(255, 80, 30);
  Func(80, 255, 15);
  Func(255, 50, 10);
  delay(300);
}

void Func(int a, int b, int c) {
  if(a < b)
  {
    for (int i = a; i < b; i+=c) {
      analogWrite(LED, i);
      delay(50);
    }
  }
  else
  {
    for (int i = a; i > b; i-=c) {
      analogWrite(LED, i);
      delay(50);
    }
  }
}

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

С нами тут все ясно. :)

nevkon
Offline
Зарегистрирован: 20.01.2015

Можно еще компактней и без функций. С использованием массива.

tagir000
Offline
Зарегистрирован: 11.06.2015

maksim пишет:

Почитайте Функции

const int LED = 10;

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

void loop() {
  Func(50, 255, 15);
  Func(255, 80, 30);
  Func(80, 255, 15);
  Func(255, 50, 10);
  delay(300);
}

void Func(int a, int b, int c) {
  if(a < b)
  {
    for (int i = a; i < b; i+=c) {
      analogWrite(LED, i);
      delay(50);
    }
  }
  else
  {
    for (int i = a; i > b; i-=c) {
      analogWrite(LED, i);
      delay(50);
    }
  }
}

 

Спасибо, буду читать)

tagir000
Offline
Зарегистрирован: 11.06.2015

nevkon пишет:

Можно еще компактней и без функций. С использованием массива.

 

Ок, буду смотреть и в этом направлении

tagir000
Offline
Зарегистрирован: 11.06.2015

Puhlyaviy пишет:
С нами тут все ясно. :)

Вы в теме не дали ни одного дельного ответа. Я не сомневаюсь, что ваши знания в этой области обширней, но это не повод ерничать.

Arhat109
Offline
Зарегистрирован: 26.05.2015

Вашу задачу можно упростить примерно так:


unsigned char starts[] = [50,255,80,255];
unsigned char ends[]   = [255,80,255,50];
unsigned char steps[]  = [15,-30,15,-10];

void setup() {
   DDRB |= _BV(2);
   TCCR1A |= COM1B1;
}

void loop() {
  for(j=4; j>0; j--) {
    for (i = starts[j]; i < end[j]; i=i+steps[j])
    {
      OCR1B = i;		// == analogWrite(LED,i);
      delay(50);
    }
  }
  delay(300);
}

 

 

Arhat109
Offline
Зарегистрирован: 26.05.2015

Не знаю какая у вас ардуинка, мнемоники регистров могут отличаться. Надо смотреть точнее или делать свои макросы с типовыми названиями функций из "wiring"

 

maksim
Offline
Зарегистрирован: 12.02.2012

Arhat109 пишет:

Вашу задачу можно упростить примерно так:

unsigned char starts[] = [50,255,80,255];
unsigned char ends[]   = [255,80,255,50];
unsigned char steps[]  = [15,-30,15,-10];

void setup() {
   DDRB |= _BV(2);
   TCCR1A |= COM1B1;
}

void loop() {
  for(j=4; j>0; j--) {
    for (i = starts[j]; i < end[j]; i=i+steps[j])
    {
      OCR1B = i;		// == analogWrite(LED,i);
      delay(50);
    }
  }
  delay(300);
}

 

Во-первых, ваш пример даже не скомпилируется из-за синтаксических ошибок.

Во-вторых, ваш пример будет работать некорректно, потому как вам нужно изучить раздел типы данныхunsigned char не принимает отрицательные значения, а точнее примет но -10 превратится в 246. Так же будет работать некорректно потому, что например, условие  i < end[j]   при   i = 255 и end[j] = 80  то есть 255 < 80 будет истинно до начала выполнения цикла.

И в-третих, а захочу вывод поменять на 6, где здесь упрощение?

Arhat109
Offline
Зарегистрирован: 26.05.2015

Конечно некорректно. Иначе его бы снесли минут в 5 как и предыдущие посты. :)

Можете исправить ошибки (это вовсе не трудно), например тупо убрать unsigned (char станет signed), а цикл по i можете изменить на такой:

for(i=starts[j]; (starts[j]<=ends[j]? i<ends[j] : i>ends[j]); i+=steps[j])

Как понимаю, задача была показать КАК можно уменьшить... :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

А чтобы легко можно было "поменять" - заменяйте Arduino.h на что-то более вменяемое и пользуйтесь типовым pinMode() и analogWrite() :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

Можно ещё упростить, если убрать условную проверку из второго цикла и вместо трех массивов сделать 2 при "последовательном проходе". Заметьте, что starts[] и ends[] регулярно повторяются... (предыдущий конец становится следующим началом) :)

maksim
Offline
Зарегистрирован: 12.02.2012

Сокращать можно вплость до асм-вставки, только вот ТС этим не сможет пользоваться от непонимания что откуда берется.

Arhat109 пишет:

например тупо убрать unsigned (char станет signed)

И все же перейдите по ссылке выше и посмотрите какие типы какие значения могут принимать.

Arhat109
Offline
Зарегистрирован: 26.05.2015

:) Ну ещё раз... это пример КАК можно упростить. То бишь "идеи":

1. Незачем повторять код, когда его можно обрамить внешним циклом;

2. "разные" данные для повторов можно хранить в памяти (и не обязательно вот так в массивах...);

3. Ну и замена больших функций на команды.

А далее, если автор захочет думать "почто не заработало" - ознакомится. Заодно и поправит. Желание разобраться - у него явно есть ... или было.

tagir000
Offline
Зарегистрирован: 11.06.2015

Arhat109 пишет:

:) Ну ещё раз... это пример КАК можно упростить. То бишь "идеи":

1. Незачем повторять код, когда его можно обрамить внешним циклом;

2. "разные" данные для повторов можно хранить в памяти (и не обязательно вот так в массивах...);

3. Ну и замена больших функций на команды.

А далее, если автор захочет думать "почто не заработало" - ознакомится. Заодно и поправит. Желание разобраться - у него явно есть ... или было.


Есть, просто много информации сразу. Надо все это переварить))

Arhat109
Offline
Зарегистрирован: 26.05.2015

Да, её много. И проблема в том, что вам, как и мне, никто её на блюдечке не поднесет, особенно тут. Смотрите исходники, не бойтесь. Не боги горшки обжигают. Я разобрался и сделал свой Arduino.h, wiring.c, wiring_analog.c и кое-что ещё ... примерно за полторы недели по 2-3 часа в день "после работы".

Вы сможете тоже. Для начала найдите библиотеку Cyberlib.h, скачайте, разберитесь. потом посмотрите темы тут по тегу Attiny13 и разного рода примеры " ... без delay()". Ну и ещё надо помнить о том, что сборка скетча в "итого" делается силами компилятора ( а вовсе не Arduino IDE! ) avr-gcc. И про много чего он "сам знает".

 

tagir000
Offline
Зарегистрирован: 11.06.2015

Arhat109 пишет:

Да, её много. И проблема в том, что вам, как и мне, никто её на блюдечке не поднесет, особенно тут. Смотрите исходники, не бойтесь. Не боги горшки обжигают. Я разобрался и сделал свой Arduino.h, wiring.c, wiring_analog.c и кое-что ещё ... примерно за полторы недели по 2-3 часа в день "после работы".

Вы сможете тоже. Для начала найдите библиотеку Cyberlib.h, скачайте, разберитесь. потом посмотрите темы тут по тегу Attiny13 и разного рода примеры " ... без delay()". Ну и ещё надо помнить о том, что сборка скетча в "итого" делается силами компилятора ( а вовсе не Arduino IDE! ) avr-gcc. И про много чего он "сам знает".

 

 

Спасибо, будем разбираться)

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

maksim пишет:

И все же перейдите по ссылке выше и посмотрите какие типы какие значения могут принимать.


Максим, товарищ сделал второй акаунт, сам спрашивает, сам отвечает. Попутно расказывая как он написал свой компилятор за полторы недели. :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

ТС-у. Вот примерно так сокращается код БЕЗ Wiring:

А это с wiring:

Имеем 868 байт кода против 1974 байта. А так, все вроде очень даже "похоже" на оригинал.

P.S. можно ещё уменьшить на размер мат. библиотеки. Тут используется длинное беззнаковое умножение. Компилять через сдивиги было уже лениво. Судя по линковщику, это больше сотни байт... :)

Arhat109
Offline
Зарегистрирован: 26.05.2015
unsigned char starts[] = {50,255,80,255,50};
char steps[] = {15,-30,15,-10};

void setup()
{

   { (*(volatile uint8_t *)(0x90)) |= 35; (*(volatile uint8_t *)(0x91)) |= 3; };
}

void loop()
{
  unsigned char i,j;

  for(j=0; j<4; j++)
  {
    for (i=starts[j]; (steps[j]>0? i < starts[j+1] : i>starts[j+1]); i=i+steps[j])
    {
      { (*(volatile uint8_t *)(0x9B)) = (unsigned char)(i>>8); (*(volatile uint8_t *)(0x9A)) = (unsigned char)(i); };
      delay(50);
    }
  }
  delay(300);
}

А это вывод препроцессора "содержательной части" скетча. :)

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

tagir000, не совсем понятна цель сокращения текста кода. Может интереснее от delay'ев избавиться, чтобы Ваше мигание весь процессор не загружало? Будет выигрыш по ресурсам. а от сокращения текста какой выигрыш? Видимость одна.