Помогите оптимизировать

Apocalyps
Offline
Зарегистрирован: 26.07.2015

Пишу автополивалку для растения, на данный момент имеется такой скетч

 


//Pin connected to ST_CP of 74HC595
#define latchPin 1
//Pin connected to SH_CP of 74HC595
#define clockPin 2
////Pin connected to DS of 74HC595
#define dataPin 0

byte dataRED;
byte dataGREEN;
byte dataArrayRED[10];
byte dataArrayGREEN[10];

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);

  dataArrayRED[0] = 0x3F; //num 0 00111111
  dataArrayRED[1] = 0x06; //num 1 00000110
  dataArrayRED[2] = 0x5B; //num 2 01011011
  dataArrayRED[3] = 0x4F; //num 3 01001111
  dataArrayRED[4] = 0x66; //num 4 01100110
  dataArrayRED[5] = 0x6D; //num 5 01101101
  dataArrayRED[6] = 0x7D; //num 6 01111101
  dataArrayRED[7] = 0x07; //num 7 00000111
  dataArrayRED[8] = 0x7F; //num 8 01111111
  dataArrayRED[9] = 0x67; //num 9 01100111



  dataArrayGREEN[0] = 0x3F; //num 0 00111111
  dataArrayGREEN[1] = 0x06; //num 1 00000110
  dataArrayGREEN[2] = 0x5B; //num 2 01011011
  dataArrayGREEN[3] = 0x4F; //num 3 01001111
  dataArrayGREEN[4] = 0x66; //num 4 01100110
  dataArrayGREEN[5] = 0x6D; //num 5 01101101
  dataArrayGREEN[6] = 0x7D; //num 6 01111101
  dataArrayGREEN[7] = 0x07; //num 7 00000111
  dataArrayGREEN[8] = 0x7F; //num 8 01111111
  dataArrayGREEN[9] = 0x67; //num 9 01100111


}

void loop() {


  

   int y = analogRead(3);
   y = constrain(y, 10, 990);
   y = y/10;

    Chislo(y);


    digitalWrite(latchPin, 0);

    shiftOut(dataPin, clockPin, dataGREEN);   
    shiftOut(dataPin, clockPin, dataRED);

    digitalWrite(latchPin, 1);

  }


void Chislo(int n){
int arr[2] = {n/10, n%10};
  if (arr[0] == 1){
    dataRED = dataArrayRED[1];
    }
else if(arr[0] == 2){
dataRED = dataArrayRED[2];
                    }
                    else if(arr[0] == 3){
dataRED = dataArrayRED[3];
                    }
                    else if(arr[0] == 4){
dataRED = dataArrayRED[4];
                    }
                    else if(arr[0] == 5){
dataRED = dataArrayRED[5];
                    }
                    else if(arr[0] == 6){
dataRED = dataArrayRED[6];
                    }
                    else if(arr[0] == 7){
dataRED = dataArrayRED[7];
                    }
                    else if(arr[0] == 8){
dataRED = dataArrayRED[8];
                    }
                    else if(arr[0] == 9){
dataRED = dataArrayRED[9];
                    }
                    else if(arr[0] == 0){
dataRED = dataArrayRED[0];
                    }

   if (arr[1] == 1){
    dataRED = dataArrayRED[1];
    }
else if(arr[1] == 2){
dataGREEN = dataArrayGREEN[2];
                    }
                    else if(arr[1] == 3){
dataGREEN = dataArrayGREEN[3];
                    }
                    else if(arr[1] == 4){
dataGREEN = dataArrayGREEN[4];
                    }
                    else if(arr[1] == 5){
dataGREEN = dataArrayGREEN[5];
                    }
                    else if(arr[1] == 6){
dataGREEN = dataArrayGREEN[6];
                    }
                    else if(arr[1] == 7){
dataGREEN = dataArrayGREEN[7];
                    }
                    else if(arr[1] == 8){
dataGREEN = dataArrayGREEN[8];
                    }
                    else if(arr[1] == 9){
dataGREEN = dataArrayGREEN[9];
                    }
                    else if(arr[1] == 0){
dataGREEN = dataArrayGREEN[0];
                    }                 
                    
                    
                    
}
  



void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {



  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);


  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);


  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);


    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {  
      pinState= 0;
    }


    digitalWrite(myDataPin, pinState);

    digitalWrite(myClockPin, 1);

    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);
}


В качестве камня используется ATTiny13. Также используется 2 регистра 74HC595. Какие моменты в коде можно улучшить, а то я пока не очень силён в программировании

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Для начала так:

//Pin connected to ST_CP of 74HC595
#define latchPin 1
//Pin connected to SH_CP of 74HC595
#define clockPin 2
////Pin connected to DS of 74HC595
#define dataPin 0

uint8_t oldValue;
byte dataFont[10] = { 
	0x3F, //num 0 00111111
	0x06, //num 1 00000110
	0x5B, //num 2 01011011
	0x4F, //num 3 01001111
	0x66, //num 4 01100110
	0x6D, //num 5 01101101
	0x7D, //num 6 01111101
	0x07, //num 7 00000111
	0x7F, //num 8 01111111
	0x67 //num 9 01100111
};

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  digitalWrite(latchPin, 1);
}

void loop() {
   uint8_t y = constrain(analogRead(3), 1, 99);
   if(oldValue != y){
      oldValue = y;
      display(y);
   }

  }
  
void display(uint8_t n){
  shiftOut(dataPin, clockPin, dataFont[n/10]);
  shiftOut(dataPin, clockPin, dataFont[n%10]);
  digitalWrite(latchPin, 0);
  digitalWrite(latchPin, 1);
}


void shiftOut(uint8_t myDataPin, uint8_t myClockPin, byte myDataOut) {



  uint8_t i=0;
  uint8_t pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);


  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);


  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);


    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {  
      pinState= 0;
    }


    digitalWrite(myDataPin, pinState);

    digitalWrite(myClockPin, 1);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);
}

Потом shiftOut   Заменить на SPI.transfer() при этои clockpin это SCK, а datapin это MOSI пин из аппаратного интерфейса SPI

#include <SPI.h>
//Pin connected to ST_CP of 74HC595 
#define latchPin 1
//Pin SH_CP of 74HC595 to SPI SCK
//Pin DS    of 74HC595 to SPI MOSI


uint8_t oldValue;
byte dataFont[10] = { 
	0x3F, //num 0 00111111
	0x06, //num 1 00000110
	0x5B, //num 2 01011011
	0x4F, //num 3 01001111
	0x66, //num 4 01100110
	0x6D, //num 5 01101101
	0x7D, //num 6 01111101
	0x07, //num 7 00000111
	0x7F, //num 8 01111111
	0x67 //num 9 01100111};

void setup() {
  SPI.begin();
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  digitalWrite(latchPin, 1);
}

void loop() {
   uint8_t y = constrain(analogRead(3), 1, 99);
   if(oldValue != y){
      oldValue = y;
      display(y);
   }
}
  
void display(uint8_t n){
  SPI.transfer(dataFont[n/10]);
  SPI.transfer(dataFont[n%10]);
  digitalWrite(latchPin, 0);
  digitalWrite(latchPin, 1);
}

Потом возможно перенести dataFont в PROGMEM - чтобы экономить оперативку. И если переменная имеет значения 0..254 то тип лучше uint8_t - сэкономит память.

SunX
SunX аватар
Offline
Зарегистрирован: 04.10.2014

Если все замечательно работает и все устраивает, зачем еще оптимизировать? Или оптимизация ради оптимизации?

Apocalyps
Offline
Зарегистрирован: 26.07.2015

память чуть ли под конец не забилась

maksmkv
Offline
Зарегистрирован: 07.04.2013

Apocalyps пишет:

Пишу автополивалку для растения, на данный момент имеется такой скетч

 


//Pin connected to ST_CP of 74HC595
#define latchPin 1
//Pin connected to SH_CP of 74HC595
#define clockPin 2
////Pin connected to DS of 74HC595
#define dataPin 0

byte dataRED;
byte dataGREEN;
byte dataArrayRED[10];
byte dataArrayGREEN[10];

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);

  dataArrayRED[0] = 0x3F; //num 0 00111111
  dataArrayRED[1] = 0x06; //num 1 00000110
  dataArrayRED[2] = 0x5B; //num 2 01011011
  dataArrayRED[3] = 0x4F; //num 3 01001111
  dataArrayRED[4] = 0x66; //num 4 01100110
  dataArrayRED[5] = 0x6D; //num 5 01101101
  dataArrayRED[6] = 0x7D; //num 6 01111101
  dataArrayRED[7] = 0x07; //num 7 00000111
  dataArrayRED[8] = 0x7F; //num 8 01111111
  dataArrayRED[9] = 0x67; //num 9 01100111



  dataArrayGREEN[0] = 0x3F; //num 0 00111111
  dataArrayGREEN[1] = 0x06; //num 1 00000110
  dataArrayGREEN[2] = 0x5B; //num 2 01011011
  dataArrayGREEN[3] = 0x4F; //num 3 01001111
  dataArrayGREEN[4] = 0x66; //num 4 01100110
  dataArrayGREEN[5] = 0x6D; //num 5 01101101
  dataArrayGREEN[6] = 0x7D; //num 6 01111101
  dataArrayGREEN[7] = 0x07; //num 7 00000111
  dataArrayGREEN[8] = 0x7F; //num 8 01111111
  dataArrayGREEN[9] = 0x67; //num 9 01100111


}

void loop() {


  

   int y = analogRead(3);
   y = constrain(y, 10, 990);
   y = y/10;

    Chislo(y);


    digitalWrite(latchPin, 0);

    shiftOut(dataPin, clockPin, dataGREEN);   
    shiftOut(dataPin, clockPin, dataRED);

    digitalWrite(latchPin, 1);

  }


void Chislo(int n){
int arr[2] = {n/10, n%10};
  if (arr[0] == 1){
    dataRED = dataArrayRED[1];
    }
else if(arr[0] == 2){
dataRED = dataArrayRED[2];
                    }
                    else if(arr[0] == 3){
dataRED = dataArrayRED[3];
                    }
                    else if(arr[0] == 4){
dataRED = dataArrayRED[4];
                    }
                    else if(arr[0] == 5){
dataRED = dataArrayRED[5];
                    }
                    else if(arr[0] == 6){
dataRED = dataArrayRED[6];
                    }
                    else if(arr[0] == 7){
dataRED = dataArrayRED[7];
                    }
                    else if(arr[0] == 8){
dataRED = dataArrayRED[8];
                    }
                    else if(arr[0] == 9){
dataRED = dataArrayRED[9];
                    }
                    else if(arr[0] == 0){
dataRED = dataArrayRED[0];
                    }

   if (arr[1] == 1){
    dataRED = dataArrayRED[1];
    }
else if(arr[1] == 2){
dataGREEN = dataArrayGREEN[2];
                    }
                    else if(arr[1] == 3){
dataGREEN = dataArrayGREEN[3];
                    }
                    else if(arr[1] == 4){
dataGREEN = dataArrayGREEN[4];
                    }
                    else if(arr[1] == 5){
dataGREEN = dataArrayGREEN[5];
                    }
                    else if(arr[1] == 6){
dataGREEN = dataArrayGREEN[6];
                    }
                    else if(arr[1] == 7){
dataGREEN = dataArrayGREEN[7];
                    }
                    else if(arr[1] == 8){
dataGREEN = dataArrayGREEN[8];
                    }
                    else if(arr[1] == 9){
dataGREEN = dataArrayGREEN[9];
                    }
                    else if(arr[1] == 0){
dataGREEN = dataArrayGREEN[0];
                    }                 
                    
                    
                    
}
  



void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {



  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);


  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);


  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);


    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {  
      pinState= 0;
    }


    digitalWrite(myDataPin, pinState);

    digitalWrite(myClockPin, 1);

    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);
}


В качестве камня используется ATTiny13. Также используется 2 регистра 74HC595. Какие моменты в коде можно улучшить, а то я пока не очень силён в программировании

 

А как и чем прошивали AtTiny чтобы  залить данный скетч??? Может есть схема устройства с обсвязкой МКAttiny + резисторы, кондеры и прочее? Хочу сам просто уйти от ардуино uno на более дешевый вариант.

Apocalyps
Offline
Зарегистрирован: 26.07.2015

Программатором MiniPro TL866CS. Так вам вроде даже можно прошивать тиньку через сам ардуино.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Apocalyps, у человека нет 300руб на Uno, а вы ему программатор за 2500 предлагаете :)

Apocalyps
Offline
Зарегистрирован: 26.07.2015

Вообщем чтобы новых тем не заводить, возникла такая проблема. Если значение переменной "y" больше 45, то начинает некоректно работать код, перестают выводится символы. Вся проблема в if конструкции, где написано "Выполнение полива"

//Пин подключенный к ST_CP на 74HC595
#define latchPin 1
//Пин подключенный к SH_CP на 74HC595
#define clockPin 2
//Пин подключенный к DS на 74HC595
#define dataPin 0

byte dataRED, dataGREEN; //значения на вывод
byte dataArrayRED[10], dataArrayGREEN[10]; //описание сегментов

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(4, OUTPUT);

  dataArrayRED[0] = 0x3F; //num 0 00111111
  dataArrayRED[1] = 0x06; //num 1 00000110
  dataArrayRED[2] = 0x5B; //num 2 01011011
  dataArrayRED[3] = 0x4F; //num 3 01001111
  dataArrayRED[4] = 0x66; //num 4 01100110
  dataArrayRED[5] = 0x6D; //num 5 01101101
  dataArrayRED[6] = 0x7D; //num 6 01111101
  dataArrayRED[7] = 0x07; //num 7 00000111
  dataArrayRED[8] = 0x7F; //num 8 01111111
  dataArrayRED[9] = 0x67; //num 9 01100111

  dataArrayGREEN[0] = 0x3F; //num 0 00111111
  dataArrayGREEN[1] = 0x06; //num 1 00000110
  dataArrayGREEN[2] = 0x5B; //num 2 01011011
  dataArrayGREEN[3] = 0x4F; //num 3 01001111
  dataArrayGREEN[4] = 0x66; //num 4 01100110
  dataArrayGREEN[5] = 0x6D; //num 5 01101101
  dataArrayGREEN[6] = 0x7D; //num 6 01111101
  dataArrayGREEN[7] = 0x07; //num 7 00000111
  dataArrayGREEN[8] = 0x7F; //num 8 01111111
  dataArrayGREEN[9] = 0x67; //num 9 01100111
}

void loop() {

  int y = analogRead(3);    //Сбор данных с АЦП, сопротивление земли
  y = (constrain(y, 10, 990)) / 10; //Уменьшение диапазона и подготовка к выводу

  /////  Выполнение полива /////
  if (y > 45) {
    digitalWrite(4, HIGH);
    delay(5000);
    digitalWrite(4, LOW);
    delay(2000);
  }

  Chislo(y);

  digitalWrite(latchPin, 0);

  shiftOut(dataPin, clockPin, dataGREEN);
  shiftOut(dataPin, clockPin, dataRED);

  digitalWrite(latchPin, 1);
}

///// Обработка числа на вывод /////
void Chislo(uint8_t n) {
  uint8_t arr[2] = {n / 10, n % 10};

  switch (arr[0]) {
    case 0:
      dataRED = dataArrayRED[0];
      break;
    case 1:
      dataRED = dataArrayRED[1];
      break;
    case 2:
      dataRED = dataArrayRED[2];
      break;
    case 3:
      dataRED = dataArrayRED[3];
      break;
    case 4:
      dataRED = dataArrayRED[4];
      break;
    case 5:
      dataRED = dataArrayRED[5];
      break;
    case 6:
      dataRED = dataArrayRED[6];
      break;
    case 7:
      dataRED = dataArrayRED[7];
      break;
    case 8:
      dataRED = dataArrayRED[8];
      break;
    case 9:
      dataRED = dataArrayRED[9];
      break;
  }

  switch (arr[1]) {
    case 0:
      dataGREEN = dataArrayGREEN[0];
      break;
    case 1:
      dataGREEN = dataArrayGREEN[1];
      break;
    case 2:
      dataGREEN = dataArrayGREEN[2];
      break;
    case 3:
      dataGREEN = dataArrayGREEN[3];
      break;
    case 4:
      dataGREEN = dataArrayGREEN[4];
      break;
    case 5:
      dataGREEN = dataArrayGREEN[5];
      break;
    case 6:
      dataGREEN = dataArrayGREEN[6];
      break;
    case 7:
      dataGREEN = dataArrayGREEN[7];
      break;
    case 8:
      dataGREEN = dataArrayGREEN[8];
      break;
    case 9:
      dataGREEN = dataArrayGREEN[9];
      break;
  }
}

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {

  int i = 0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  for (i = 7; i >= 0; i--)  {
    digitalWrite(myClockPin, 0);

    if ( myDataOut & (1 << i) ) {
      pinState = 1;
    }
    else {
      pinState = 0;
    }

    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }


  digitalWrite(myClockPin, 0);
}

 

Apocalyps
Offline
Зарегистрирован: 26.07.2015

dimax пишет:

Apocalyps, у человека нет 300руб на Uno, а вы ему программатор за 2500 предлагаете :)

я просто подумал, что Uno у него в наличии

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Apocalyps, по вопросу -вы как раз столкнулись с тем, почему не советуют использовать delay. Нужно убирать delay ,лучше вынести полив в отдельную функцию,  Из loop контролировать в какой стадии находится процесс полива через сравнение millis().  В теме "мигаем без delay" можно посмотреть как решать такую задачу.

Apocalyps
Offline
Зарегистрирован: 26.07.2015

dimax, используя алгоритм из той статьи...короче у меня бинарник больше 1024 байт получается :-(

Dexxx
Offline
Зарегистрирован: 28.07.2015

В плане оптимизации предлагаю заменить строки 65-129 кода из сообщения #7 вот чем:

dataRED = dataArrayRED[arr[0]];
dataGREEN = dataArrayGREEN[arr[1]];

 

Apocalyps
Offline
Зарегистрирован: 26.07.2015

Dexxx пишет:

В плане оптимизации предлагаю заменить строки 65-129 кода из сообщения #7 вот чем:

dataRED = dataArrayRED[arr[0]];
dataGREEN = dataArrayGREEN[arr[1]];

 

Сейчас просто нет возможности проверить, а что я этими строками изменю? Я смогу отказаться от конструкций case-break?

Dexxx
Offline
Зарегистрирован: 28.07.2015

Именно.

Вы используете switch() для того что бы проверить например будет ли элемент номер 0 равен 0 и если да, то берете элементы номер 0 массивов dataArrayRED[] и dataArrayGREEN[]. И так для всего диапазона этих массивов.

В данном случает такие проверки не нужны, можно сразу подставить значение элемета массива Arr[] в качестве номеров элементов массивов dataArrayRED[] и dataArrayGREEN[].

Так избавляемся от громоздких конструкций switch() заменяя их на эти две строки.

Кроме того, от массива Arr[] тоже можно избавиться, и тогда фунция примет следующий вид:

void Chislo(uint8_t n) {
  dataRED = dataArrayRED[n/10];
  dataGREEN = dataArrayGREEN[n%10];
}

И возникает вопрос - а есть ли смысл в этой фунции из двух строк. Если склоняемся к мысли, что смысл есть, то так и оставляем. Если все таки нет и хватит поясняющего комментария, то в функции loop() заменяем вызов функции Chislo(y); на следующее:

 //описание действий
  dataRED = dataArrayRED[y/10];
  dataGREEN = dataArrayGREEN[y%10];

Получается, что избавились от громоздкой функции и ее вызова, сократив тем самым объем кода примерно в два раза.

Apocalyps
Offline
Зарегистрирован: 26.07.2015

Dexxx пишет:

 //описание действий
  dataRED = dataArrayRED[y/10];
  dataGREEN = dataArrayGREEN[y%10];

Получается, что избавились от громоздкой функции и ее вызова, сократив тем самым объем кода примерно в два раза.

Замечательно! 202 байта сэкономлено