Картинка для привлечения внимания

На днях появилась подработка, поступил заказ записать скетч на ардуино. Простенький, но объёмный. С повторяющимися блоками. Нужно было управлять каждым портом Arduino Mega отдельно, при получении команды по Uart. Отправляешь символ — и светодиод (к примеру) загорается на определенное время. Написал скетч на 2 команды, скинул заказчику для тестов, получил предоплату. Дальше, нужно было масштабировать на все порты.

Для начала я честно попробовал руками. Написав первые 26 #define, энтузиазм иссяк. Я пошел подышать свежим воздухом, и вспомнил, что у меня на ПК (Win 7 x64), уже установлен Python 3.6 из дистрибутива Anaconda. Кстати, это наиболее удобный способ установки Python`а на Windows, т.к. всё уже включено и настроено по умолчанию, и есть пакетный менеджер.

Итак, приступим.

Создаем папку, в ней пустой файл, я назвал его «arduino_gen.py» и bat файл «start_py.bat» со следующим содержимым:

python.exe arduino_gen.py > code_out.txt
@pause


Этот файл нам потребуется, для запуска программы на Python`е
Теперь мы напишем программку, которая сгенерирует нам необходимый код для Arduino.

Для начала, создадим два списка со всеми необходимыми нам значениями, которые мы будем подставлять в код. Имена могут быть любыми, дело вкуса.

chap = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'] 
num = ['2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53']

И две переменные, для перебора списков

i = 0
k = 0

И теперь создадим цикл для генерации #define PIN_a 2… #define PIN_Z 53

iteration1 = True

while iteration1:

	print('#define PIN_' + chap[i] + ' ' + num[k])

	i = i + 1
	k = k + 1
	if i > 51:
		iteration1 = False

print()

Сохраняем, запускаем файл «start_py.bat»

результат
#define PIN_a 2
#define PIN_b 3
#define PIN_c 4
#define PIN_d 5
#define PIN_e 6
#define PIN_f 7
#define PIN_g 8
#define PIN_h 9
#define PIN_i 10
#define PIN_j 11
#define PIN_k 12
#define PIN_l 13
#define PIN_m 14
#define PIN_n 15
#define PIN_o 16
#define PIN_p 17
#define PIN_q 18
#define PIN_r 19
#define PIN_s 20
#define PIN_t 21
#define PIN_u 22
#define PIN_v 23
#define PIN_w 24
#define PIN_x 25
#define PIN_y 26
#define PIN_z 27
#define PIN_A 28
#define PIN_B 29
#define PIN_C 30
#define PIN_D 31
#define PIN_E 32
#define PIN_F 33
#define PIN_G 34
#define PIN_H 35
#define PIN_I 36
#define PIN_J 37
#define PIN_K 38
#define PIN_L 39
#define PIN_M 40
#define PIN_N 41
#define PIN_O 42
#define PIN_P 43
#define PIN_Q 44
#define PIN_R 45
#define PIN_S 46
#define PIN_T 47
#define PIN_U 48
#define PIN_V 49
#define PIN_W 50
#define PIN_X 51
#define PIN_Y 52
#define PIN_Z 53


Если мы хотим вывести результат сразу в файл, тогда допишем:

python.exe arduino_gen.py > code_out.txt
@pause


В результате, мы получим файл «code_out.txt » из которого, код удобно копировать в скетч в лучших традициях Arduino.

Уже на этом этапе, у меня возник вопрос, хватит ли у Arduino памяти, если сгенерировать большое количество переменных. Однако, забегая вперед, скажу, что памяти вполне хватило, в чем можно убедиться про компиляции скетча.



Далее, я приведу остальной код, в котором несложно разобраться. Но, для начала, рассмотрим

Упрощенный скетч
// Задаем пины 
#define PIN_a 2 
#define PIN_b 3 


//Задаем время 
#define TIME_a 10000 
#define TIME_b 10000 


//логическое состояние светодиода 
boolean ledState_a = false; 
boolean ledState_b = false; 


int time_a = 0; 
int time_b = 0; 


void setup() { 
// инициализация 
Serial.begin(9600); 
for (int i = 2; i <= 53; i++) 
pinMode(i, OUTPUT); 
} 
void loop() { 
if (Serial.available() >0) { 
int x = Serial.read(); 


//a 
if(x == 'a'){ 
ledState_a = true; 
time_a = TIME_a; 
x = 0; 
} 

//b 
if(x == 'b'){ 
ledState_b = true; 
time_b = TIME_b; 
x = 0; 
} 

} 
// Исполнительная часть 
//a 
if(ledState_a == true){ 
time_a = time_a - 1; 
digitalWrite(PIN_a, HIGH); 
} 

if(time_a == 0){ 
ledState_a = false; 
} 

if(ledState_a == false){ 
digitalWrite(PIN_a, LOW); 
} 
//b 
if(ledState_b == true){ 
time_b = time_b - 1; 
} 
if(time_b > 0){ 
digitalWrite(PIN_b, HIGH); 
} 
if(time_b == 0){ 
digitalWrite(PIN_b, LOW); 
ledState_b = false; 
} 
//Задержка в конце 
delay(1); 
}


Здесь, нужно сгенерировать 4 блока кода в начале. И два блока в конце. В последствии, заказчик захотел изменить логику работы, чтобы при приходе заглавной буквы менялось состояние выхода. Я переписал участок кода:

//Когда приходит большая буква - меняем состояние 
//A
if(x == 'A'){
    digitalWrite (PIN_A, !digitalRead(PIN_A));
    x = 0;
    }

И масштабировал при помощи Python'а

i = 26
iteration7 = True
while iteration7:
	print()
	print('//' + chap[i])
	print("if(x == '" + chap[i] + "'){")
	print('    digitalWrite (PIN_' + chap[i] + ', !digitalRead(PIN_' + chap[i] + '));')
	print('    x = 0;')
	print('    }')
	i = i + 1
	if i > 51:
		iteration7 = False
print()
print('}')
print()

Вот, что в итоге получилось.

Очень длинный код, я предупреждал!
// Задаем пины
#define PIN_a 2
#define PIN_b 3
#define PIN_c 4
#define PIN_d 5
#define PIN_e 6
#define PIN_f 7
#define PIN_g 8
#define PIN_h 9
#define PIN_i 10
#define PIN_j 11
#define PIN_k 12
#define PIN_l 13
#define PIN_m 14
#define PIN_n 15
#define PIN_o 16
#define PIN_p 17
#define PIN_q 18
#define PIN_r 19
#define PIN_s 20
#define PIN_t 21
#define PIN_u 22
#define PIN_v 23
#define PIN_w 24
#define PIN_x 25
#define PIN_y 26
#define PIN_z 27
#define PIN_A 28
#define PIN_B 29
#define PIN_C 30
#define PIN_D 31
#define PIN_E 32
#define PIN_F 33
#define PIN_G 34
#define PIN_H 35
#define PIN_I 36
#define PIN_J 37
#define PIN_K 38
#define PIN_L 39
#define PIN_M 40
#define PIN_N 41
#define PIN_O 42
#define PIN_P 43
#define PIN_Q 44
#define PIN_R 45
#define PIN_S 46
#define PIN_T 47
#define PIN_U 48
#define PIN_V 49
#define PIN_W 50
#define PIN_X 51
#define PIN_Y 52
#define PIN_Z 53

//Задаем время
//Здесь, скорее всего, потребуется поправка
//Например, 1 секунда может быть не 1000, а 865, к примеру.
//Нужно будет секундомером померить, и, если необходимо,
// уменьшить на некий коофициент
#define TIME_a 1000
#define TIME_b 1000
#define TIME_c 1000
#define TIME_d 1000
#define TIME_e 1000
#define TIME_f 1000
#define TIME_g 1000
#define TIME_h 1000
#define TIME_i 1000
#define TIME_j 1000
#define TIME_k 1000
#define TIME_l 1000
#define TIME_m 1000
#define TIME_n 1000
#define TIME_o 1000
#define TIME_p 1000
#define TIME_q 1000
#define TIME_r 1000
#define TIME_s 1000
#define TIME_t 1000
#define TIME_u 1000
#define TIME_v 1000
#define TIME_w 1000
#define TIME_x 1000
#define TIME_y 1000
#define TIME_z 1000
#define TIME_A 1000
#define TIME_B 1000
#define TIME_C 1000
#define TIME_D 1000
#define TIME_E 1000
#define TIME_F 1000
#define TIME_G 1000
#define TIME_H 1000
#define TIME_I 1000
#define TIME_J 1000
#define TIME_K 1000
#define TIME_L 1000
#define TIME_M 1000
#define TIME_N 1000
#define TIME_O 1000
#define TIME_P 1000
#define TIME_Q 1000
#define TIME_R 1000
#define TIME_S 1000
#define TIME_T 1000
#define TIME_U 1000
#define TIME_V 1000
#define TIME_W 1000
#define TIME_X 1000
#define TIME_Y 1000
#define TIME_Z 1000

//логическое состояние светодиода (да / нет)
boolean ledState_a = false;
boolean ledState_b = false;
boolean ledState_c = false;
boolean ledState_d = false;
boolean ledState_e = false;
boolean ledState_f = false;
boolean ledState_g = false;
boolean ledState_h = false;
boolean ledState_i = false;
boolean ledState_j = false;
boolean ledState_k = false;
boolean ledState_l = false;
boolean ledState_m = false;
boolean ledState_n = false;
boolean ledState_o = false;
boolean ledState_p = false;
boolean ledState_q = false;
boolean ledState_r = false;
boolean ledState_s = false;
boolean ledState_t = false;
boolean ledState_u = false;
boolean ledState_v = false;
boolean ledState_w = false;
boolean ledState_x = false;
boolean ledState_y = false;
boolean ledState_z = false;
boolean ledState_A = false;
boolean ledState_B = false;
boolean ledState_C = false;
boolean ledState_D = false;
boolean ledState_E = false;
boolean ledState_F = false;
boolean ledState_G = false;
boolean ledState_H = false;
boolean ledState_I = false;
boolean ledState_J = false;
boolean ledState_K = false;
boolean ledState_L = false;
boolean ledState_M = false;
boolean ledState_N = false;
boolean ledState_O = false;
boolean ledState_P = false;
boolean ledState_Q = false;
boolean ledState_R = false;
boolean ledState_S = false;
boolean ledState_T = false;
boolean ledState_U = false;
boolean ledState_V = false;
boolean ledState_W = false;
boolean ledState_X = false;
boolean ledState_Y = false;
boolean ledState_Z = false;

//Переменные, для хранения времени
int time_a = 0;
int time_b = 0;
int time_c = 0;
int time_d = 0;
int time_e = 0;
int time_f = 0;
int time_g = 0;
int time_h = 0;
int time_i = 0;
int time_j = 0;
int time_k = 0;
int time_l = 0;
int time_m = 0;
int time_n = 0;
int time_o = 0;
int time_p = 0;
int time_q = 0;
int time_r = 0;
int time_s = 0;
int time_t = 0;
int time_u = 0;
int time_v = 0;
int time_w = 0;
int time_x = 0;
int time_y = 0;
int time_z = 0;
int time_A = 0;
int time_B = 0;
int time_C = 0;
int time_D = 0;
int time_E = 0;
int time_F = 0;
int time_G = 0;
int time_H = 0;
int time_I = 0;
int time_J = 0;
int time_K = 0;
int time_L = 0;
int time_M = 0;
int time_N = 0;
int time_O = 0;
int time_P = 0;
int time_Q = 0;
int time_R = 0;
int time_S = 0;
int time_T = 0;
int time_U = 0;
int time_V = 0;
int time_W = 0;
int time_X = 0;
int time_Y = 0;
int time_Z = 0;

void setup() {
// не стал переписывать инициализацию
Serial.begin(9600);
for (int i = 2; i <= 53; i++)
pinMode(i, OUTPUT);
}
void loop() {
if (Serial.available() >0) {
int x = Serial.read();

//Проверяем, что у нас пришло

//a
if(x == 'a'){
ledState_a = true;
time_a = TIME_a;
x = 0;
}

//b
if(x == 'b'){
ledState_b = true;
time_b = TIME_b;
x = 0;
}

//c
if(x == 'c'){
ledState_c = true;
time_c = TIME_c;
x = 0;
}

//d
if(x == 'd'){
ledState_d = true;
time_d = TIME_d;
x = 0;
}

//e
if(x == 'e'){
ledState_e = true;
time_e = TIME_e;
x = 0;
}

//f
if(x == 'f'){
ledState_f = true;
time_f = TIME_f;
x = 0;
}

//g
if(x == 'g'){
ledState_g = true;
time_g = TIME_g;
x = 0;
}

//h
if(x == 'h'){
ledState_h = true;
time_h = TIME_h;
x = 0;
}

//i
if(x == 'i'){
ledState_i = true;
time_i = TIME_i;
x = 0;
}

//j
if(x == 'j'){
ledState_j = true;
time_j = TIME_j;
x = 0;
}

//k
if(x == 'k'){
ledState_k = true;
time_k = TIME_k;
x = 0;
}

//l
if(x == 'l'){
ledState_l = true;
time_l = TIME_l;
x = 0;
}

//m
if(x == 'm'){
ledState_m = true;
time_m = TIME_m;
x = 0;
}

//n
if(x == 'n'){
ledState_n = true;
time_n = TIME_n;
x = 0;
}

//o
if(x == 'o'){
ledState_o = true;
time_o = TIME_o;
x = 0;
}

//p
if(x == 'p'){
ledState_p = true;
time_p = TIME_p;
x = 0;
}

//q
if(x == 'q'){
ledState_q = true;
time_q = TIME_q;
x = 0;
}

//r
if(x == 'r'){
ledState_r = true;
time_r = TIME_r;
x = 0;
}

//s
if(x == 's'){
ledState_s = true;
time_s = TIME_s;
x = 0;
}

//t
if(x == 't'){
ledState_t = true;
time_t = TIME_t;
x = 0;
}

//u
if(x == 'u'){
ledState_u = true;
time_u = TIME_u;
x = 0;
}

//v
if(x == 'v'){
ledState_v = true;
time_v = TIME_v;
x = 0;
}

//w
if(x == 'w'){
ledState_w = true;
time_w = TIME_w;
x = 0;
}

//x
if(x == 'x'){
ledState_x = true;
time_x = TIME_x;
x = 0;
}

//y
if(x == 'y'){
ledState_y = true;
time_y = TIME_y;
x = 0;
}

//z
if(x == 'z'){
ledState_z = true;
time_z = TIME_z;
x = 0;
}
//Когда приходит большая буква — меняем состояние

//A
if(x == 'A'){
digitalWrite (PIN_A, !digitalRead(PIN_A));
x = 0;
}

//B
if(x == 'B'){
digitalWrite (PIN_B, !digitalRead(PIN_B));
x = 0;
}

//C
if(x == 'C'){
digitalWrite (PIN_C, !digitalRead(PIN_C));
x = 0;
}

//D
if(x == 'D'){
digitalWrite (PIN_D, !digitalRead(PIN_D));
x = 0;
}

//E
if(x == 'E'){
digitalWrite (PIN_E, !digitalRead(PIN_E));
x = 0;
}

//F
if(x == 'F'){
digitalWrite (PIN_F, !digitalRead(PIN_F));
x = 0;
}

//G
if(x == 'G'){
digitalWrite (PIN_G, !digitalRead(PIN_G));
x = 0;
}

//H
if(x == 'H'){
digitalWrite (PIN_H, !digitalRead(PIN_H));
x = 0;
}

//I
if(x == 'I'){
digitalWrite (PIN_I, !digitalRead(PIN_I));
x = 0;
}

//J
if(x == 'J'){
digitalWrite (PIN_J, !digitalRead(PIN_J));
x = 0;
}

//K
if(x == 'K'){
digitalWrite (PIN_K, !digitalRead(PIN_K));
x = 0;
}

//L
if(x == 'L'){
digitalWrite (PIN_L, !digitalRead(PIN_L));
x = 0;
}

//M
if(x == 'M'){
digitalWrite (PIN_M, !digitalRead(PIN_M));
x = 0;
}

//N
if(x == 'N'){
digitalWrite (PIN_N, !digitalRead(PIN_N));
x = 0;
}

//O
if(x == 'O'){
digitalWrite (PIN_O, !digitalRead(PIN_O));
x = 0;
}

//P
if(x == 'P'){
digitalWrite (PIN_P, !digitalRead(PIN_P));
x = 0;
}

//Q
if(x == 'Q'){
digitalWrite (PIN_Q, !digitalRead(PIN_Q));
x = 0;
}

//R
if(x == 'R'){
digitalWrite (PIN_R, !digitalRead(PIN_R));
x = 0;
}

//S
if(x == 'S'){
digitalWrite (PIN_S, !digitalRead(PIN_S));
x = 0;
}

//T
if(x == 'T'){
digitalWrite (PIN_T, !digitalRead(PIN_T));
x = 0;
}

//U
if(x == 'U'){
digitalWrite (PIN_U, !digitalRead(PIN_U));
x = 0;
}

//V
if(x == 'V'){
digitalWrite (PIN_V, !digitalRead(PIN_V));
x = 0;
}

//W
if(x == 'W'){
digitalWrite (PIN_W, !digitalRead(PIN_W));
x = 0;
}

//X
if(x == 'X'){
digitalWrite (PIN_X, !digitalRead(PIN_X));
x = 0;
}

//Y
if(x == 'Y'){
digitalWrite (PIN_Y, !digitalRead(PIN_Y));
x = 0;
}

//Z
if(x == 'Z'){
digitalWrite (PIN_Z, !digitalRead(PIN_Z));
x = 0;
}

}
//a
if(ledState_a == true){
time_a = time_a — 1;
digitalWrite(PIN_a, HIGH);
}

if(time_a == 0){
ledState_a = false;
}

if(ledState_a == false){
digitalWrite(PIN_a, LOW);
}

//b
if(ledState_b == true){
time_b = time_b — 1;
digitalWrite(PIN_b, HIGH);
}

if(time_b == 0){
ledState_b = false;
}

if(ledState_b == false){
digitalWrite(PIN_b, LOW);
}

//c
if(ledState_c == true){
time_c = time_c — 1;
digitalWrite(PIN_c, HIGH);
}

if(time_c == 0){
ledState_c = false;
}

if(ledState_c == false){
digitalWrite(PIN_c, LOW);
}

//d
if(ledState_d == true){
time_d = time_d — 1;
digitalWrite(PIN_d, HIGH);
}

if(time_d == 0){
ledState_d = false;
}

if(ledState_d == false){
digitalWrite(PIN_d, LOW);
}

//e
if(ledState_e == true){
time_e = time_e — 1;
digitalWrite(PIN_e, HIGH);
}

if(time_e == 0){
ledState_e = false;
}

if(ledState_e == false){
digitalWrite(PIN_e, LOW);
}

//f
if(ledState_f == true){
time_f = time_f — 1;
digitalWrite(PIN_f, HIGH);
}

if(time_f == 0){
ledState_f = false;
}

if(ledState_f == false){
digitalWrite(PIN_f, LOW);
}

//g
if(ledState_g == true){
time_g = time_g — 1;
digitalWrite(PIN_g, HIGH);
}

if(time_g == 0){
ledState_g = false;
}

if(ledState_g == false){
digitalWrite(PIN_g, LOW);
}

//h
if(ledState_h == true){
time_h = time_h — 1;
digitalWrite(PIN_h, HIGH);
}

if(time_h == 0){
ledState_h = false;
}

if(ledState_h == false){
digitalWrite(PIN_h, LOW);
}

//i
if(ledState_i == true){
time_i = time_i — 1;
digitalWrite(PIN_i, HIGH);
}

if(time_i == 0){
ledState_i = false;
}

if(ledState_i == false){
digitalWrite(PIN_i, LOW);
}

//j
if(ledState_j == true){
time_j = time_j — 1;
digitalWrite(PIN_j, HIGH);
}

if(time_j == 0){
ledState_j = false;
}

if(ledState_j == false){
digitalWrite(PIN_j, LOW);
}

//k
if(ledState_k == true){
time_k = time_k — 1;
digitalWrite(PIN_k, HIGH);
}

if(time_k == 0){
ledState_k = false;
}

if(ledState_k == false){
digitalWrite(PIN_k, LOW);
}

//l
if(ledState_l == true){
time_l = time_l — 1;
digitalWrite(PIN_l, HIGH);
}

if(time_l == 0){
ledState_l = false;
}

if(ledState_l == false){
digitalWrite(PIN_l, LOW);
}

//m
if(ledState_m == true){
time_m = time_m — 1;
digitalWrite(PIN_m, HIGH);
}

if(time_m == 0){
ledState_m = false;
}

if(ledState_m == false){
digitalWrite(PIN_m, LOW);
}

//n
if(ledState_n == true){
time_n = time_n — 1;
digitalWrite(PIN_n, HIGH);
}

if(time_n == 0){
ledState_n = false;
}

if(ledState_n == false){
digitalWrite(PIN_n, LOW);
}

//o
if(ledState_o == true){
time_o = time_o — 1;
digitalWrite(PIN_o, HIGH);
}

if(time_o == 0){
ledState_o = false;
}

if(ledState_o == false){
digitalWrite(PIN_o, LOW);
}

//p
if(ledState_p == true){
time_p = time_p — 1;
digitalWrite(PIN_p, HIGH);
}

if(time_p == 0){
ledState_p = false;
}

if(ledState_p == false){
digitalWrite(PIN_p, LOW);
}

//q
if(ledState_q == true){
time_q = time_q — 1;
digitalWrite(PIN_q, HIGH);
}

if(time_q == 0){
ledState_q = false;
}

if(ledState_q == false){
digitalWrite(PIN_q, LOW);
}

//r
if(ledState_r == true){
time_r = time_r — 1;
digitalWrite(PIN_r, HIGH);
}

if(time_r == 0){
ledState_r = false;
}

if(ledState_r == false){
digitalWrite(PIN_r, LOW);
}

//s
if(ledState_s == true){
time_s = time_s — 1;
digitalWrite(PIN_s, HIGH);
}

if(time_s == 0){
ledState_s = false;
}

if(ledState_s == false){
digitalWrite(PIN_s, LOW);
}

//t
if(ledState_t == true){
time_t = time_t — 1;
digitalWrite(PIN_t, HIGH);
}

if(time_t == 0){
ledState_t = false;
}

if(ledState_t == false){
digitalWrite(PIN_t, LOW);
}

//u
if(ledState_u == true){
time_u = time_u — 1;
digitalWrite(PIN_u, HIGH);
}

if(time_u == 0){
ledState_u = false;
}

if(ledState_u == false){
digitalWrite(PIN_u, LOW);
}

//v
if(ledState_v == true){
time_v = time_v — 1;
digitalWrite(PIN_v, HIGH);
}

if(time_v == 0){
ledState_v = false;
}

if(ledState_v == false){
digitalWrite(PIN_v, LOW);
}

//w
if(ledState_w == true){
time_w = time_w — 1;
digitalWrite(PIN_w, HIGH);
}

if(time_w == 0){
ledState_w = false;
}

if(ledState_w == false){
digitalWrite(PIN_w, LOW);
}

//x
if(ledState_x == true){
time_x = time_x — 1;
digitalWrite(PIN_x, HIGH);
}

if(time_x == 0){
ledState_x = false;
}

if(ledState_x == false){
digitalWrite(PIN_x, LOW);
}

//y
if(ledState_y == true){
time_y = time_y — 1;
digitalWrite(PIN_y, HIGH);
}

if(time_y == 0){
ledState_y = false;
}

if(ledState_y == false){
digitalWrite(PIN_y, LOW);
}

//z
if(ledState_z == true){
time_z = time_z — 1;
digitalWrite(PIN_z, HIGH);
}

if(time_z == 0){
ledState_z = false;
}

if(ledState_z == false){
digitalWrite(PIN_z, LOW);
}

delay(1);

}

Код на Python`е, который генерирует это безобразие
chap = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'] 

num = ['2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53']

i = 0
k = 0

iteration1 = True

while iteration1:

	print('#define PIN_' + chap[i] + ' ' + num[k])

	i = i + 1
	k = k + 1
	if i > 51:
		iteration1 = False

print()

i = 0
iteration2 = True
while iteration2:
	print('#define TIME_' + chap[i] + ' ' + '1000')
	i = i + 1
	if i > 51:
		iteration2 = False

print()

i = 0
iteration3 = True
while iteration3:
	print('boolean ledState_' + chap[i] + ' ' + '= false;')
	i = i + 1
	if i > 51:
		iteration3 = False

print()

i = 0
iteration4 = True
while iteration4:
	print('int time_' + chap[i] + ' ' + '= 0;')
	i = i + 1
	if i > 51:
		iteration4 = False

i = 0
iteration5 = True
while iteration5:
	print()
	print('//' + chap[i])
	print("if(x == '" + chap[i] + "'){")
	print('    ledState_' + chap[i] + ' = true;')
	print('    time_' + chap[i] + ' = TIME_' + chap[i] + ';')
	print('    x = 0;')
	print('    }')
	i = i + 1
	if i > 51:
		iteration5 = False

print()
print('}')
print()

i = 0
iteration6 = True
while iteration6:
	print()

	print('//' + chap[i])
	print("if(ledState_" + chap[i] + " == true){")
	print('    time_' + chap[i] + '  = time_' + chap[i] + ' - 1;')
	print('    digitalWrite(PIN_' + chap[i] + ', HIGH);')
	print('    }')
	print()

	print("if(time_" + chap[i] + " == 0){")
	print('    ledState_' + chap[i] + ' = false;')
	print('    }')
	print()

	print("if(ledState_" + chap[i] + " == false){")
	print('    digitalWrite(PIN_' + chap[i] + ', LOW);')
	print('    }')

	i = i + 1
	if i > 51:
		iteration6 = False

print()
print('delay(1);')
print()
print('}')

print('NEW VERSION')

i = 26
iteration7 = True
while iteration7:
	print()
	print('//' + chap[i])
	print("if(x == '" + chap[i] + "'){")
	print('    digitalWrite (PIN_' + chap[i] + ', !digitalRead(PIN_' + chap[i] + '));')
	print('    x = 0;')
	print('    }')
	i = i + 1
	if i > 51:
		iteration7 = False

print()
print('}')
print()
 


P.S.: Одной из целей автоматизации было избежать человеческих ошибок, каково же было моё удивление, когда скетч отказался компилироваться. Причина была в том, что я поторопился и написал алфавит с одной повторяющейся буковой.

P.P.S.: Заказчик был ужасно доволен, заплатил больше, чем договаривались, и даже разрешил поделиться кодом с читателями.

Учите Python, господа!
Поделиться с друзьями
-->

Комментарии (27)


  1. Gryphon88
    26.07.2017 15:02
    +2

    На что только люди не идут, чтобы не учить макросы вообще и x-macro c _Generic в частности…


  1. Reckyxxx
    26.07.2017 15:33

    Написав первые 26 #define, энтузиазм иссяк.

    Тогда хотя бы:
    chap = [chr(x) for x in range(97, 123)] + [chr(x).upper() for x in range(97, 123)]
    num = [str(x) for x in range(2, 54)]
    


    1. qark
      26.07.2017 15:59

      А лучше нагуглить или вспомнить string.ascii_letters и string.ascii_uppercase. Тогда и первого P.S. не было бы :)


  1. Akon32
    26.07.2017 15:59
    +1

    Ъ-индусский код!


    А с циклами и массивами пробовали то же самое написать?


    1. nochkin
      26.07.2017 18:34
      +1

      Так это было на заказ сделано. Наверно, оплата шла за каждую строчку кода.


  1. vyacheslavteplyakov
    26.07.2017 15:59
    +1

    Как говориться как кто умеет, была бы лень, а прогресс будет. Я даже не знаю как поступил был, скорее всего вообще использовал бы XL…
    image
    хотя дальше все сложнее, но мне просто лень.


    1. DEM_dwg
      26.07.2017 17:15

      Решение с экселем выглядит очень лаконично, учитывая что сделать это можно меньше чем за минуту.


      1. vyacheslavteplyakov
        26.07.2017 17:56

        Да, буквально две «формулы» и протянуть вниз.
        Первый столбик коды символов, второй рыба, третий превращение этих самых символов из первого столбика в буквы. Можно конечно завести алфавитный список в XL и «проятнуть», но это дольше. 4й порты (забыл их добавить к результату), ну и последний сращиваем все через & в одну строку, профит!


    1. semen-pro
      26.07.2017 18:29

      Excel мало подходит, для такого кода

      if(ledState_a == true){ 
      time_a = time_a - 1; 
      digitalWrite(PIN_a, HIGH); 
      } 
      


      1. QDeathNick
        26.07.2017 22:47

        Очень подходит, попробуйте. Правда с телефона будет не просто это сделать, а вот с мышкой буквально секунды занимает.


  1. Stronix
    26.07.2017 16:30

    Вот это индусятина) Хотя бы как-то так:

    for ch in string.ascii_letters:
        print('#define PIN_' + ch, string.ascii_letters.index(ch) + 2)
    

    Учите Python, господа!

    Ну, хоть самокритично)


    1. Lertmind
      26.07.2017 17:18
      +1

      По-моему так получше будет:

      import string
      for i, ch in enumerate(string.ascii_letters):
          print("#define PIN_{} {}".format(ch, i + 2))
      


      1. Stronix
        27.07.2017 08:40

        Тогда уж

        import string
        for i, ch in enumerate(string.ascii_letters, start=2):
            print("#define PIN_{} {}".format(ch, i))
        


  1. inferrna
    26.07.2017 16:44

    Для питона есть удобный темплейтный движок mako — с ним можно получить читаемый код без этих обёрток в виде print(..). В частности, на нём работает кодогенерация в pyopencl.


  1. kAIST
    26.07.2017 16:57

    А зачем anaconda, если python из коробки в windows и так уже работает нормально? Какие то ещё батники писать… При установке нужно просто галочку поставить, чтоб нужные пути в path попали или сделать потом это ручками. А так и pip уже давно в комплекте идёт и работает прекрасно.


  1. foxin
    26.07.2017 17:03
    +2

    Я понимаю, что можно не быть хорошим программистом и при этом писать программы, хотя бы для ардуино. Но выкладывать это на хабр — как-то странно.


    1. Gryphon88
      26.07.2017 17:30
      +1

      На самом деле вопрос про внешнюю кодогенерацию интересный, потому что С:
      — старый и не имеет части возможностей более новых языков. Например, объекты в чистом С дают неслабый оверхед.
      — многословный
      — с системой макросов, сложных и неинтуитивных. Например, иногда очень хочется сделать define внутри define, или сделать дефайн с генерацией имени через конкатенацию строк в макросе, или использовать if в макросе с раскруткой в compile time, или разделить токен в макросе на части — а низзя, если не брать в расчет извращения типа
      g++ -E input.cpp | g++ -c -x c++ - -o output.o

      примерно те же проблемы имеет asm
      Поэтому в принципе разумно написать короткий понятный код на питоне или ещё на чём, который будет генерировать неподдерживаемый, но шустрый код на С/asm. Проблема в том, что нет устоявшегося мнения, как это делать «правильно»


      1. tronix286
        27.07.2017 07:59

        На питоне простой понятный код будет тормозить, бай дизайн. Си конечно не идеален, и с обьектами там не очень. Но он быстрый. Просто нужно понимать разницу между задачей светодиодом моргнуть и скажем одновременного приема с трех SPI сообщений, с парсингом.


        1. Gryphon88
          27.07.2017 13:16

          Вот про это я и говорю, что нет устоявшегося мнения про «правильно». Если у нас задача в питоне сгенерировать текстовый файл на несколько тысяч строк, то он навряд ли будет тормозить так, что это станет неприемлемо, но зато мы теоретически сможем помочь gcc с оптимизацией и отбить время на компиляции. Задача становится ещё интереснее, если мы генерируем код на asm, потому, например, что там мы можем выходить из прерывания не туда, откуда в него вошли; такой код сложен в поддержке, но если его писать не на асме, может получить оба достоинства.
          Правда, это ни у кого не получилось, чтоб аж прям выстрелить. Разработка компиляторов или кодогенераторов на прологе всплывает с 70х и по наши дни, но значимого выхлопа не видно.

          Ссылки на компиляторы и кодогенераторы на прологе
          1.Applied logic — it's use and implementation as programming tool. Technical note, 1977
          2. Parsing and Compiling Using Prolog, 1987
          3. An implementation of retargetable code generators in prolog, 1988
          4. Prolog based retargetable code generation, 1989
          5. Code Generation — Concepts, Tools, Techniques: Proceedings of the International Workshop on Code Generation, Dagstuhl, Germany, 20–24 May 1991 глава 5, Prolog Implementation,
          6. The Practice of Prolog, глава 4, Developing a parallelising Pascal compiler in Prolog (про Паскаль — потому что написано в стиле пошагового туториала), 1990

          Видел и публикации 2010х, но там не так интересно и более специализировано


  1. Konachan700
    26.07.2017 19:06
    +1

    КДПВ, если расфокусировать зрение, тонко намекает нам на качество кода под катом.
    Но если платили за количество строк, то понимаю, зачем так сурово…


  1. QDeathNick
    26.07.2017 22:39

    написал алфавит

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


  1. kolodkin
    27.07.2017 01:38

    Можно как-то так:

    #define FIRST_PIN  2
    #define LAST_PIN  27
    
    
    #define PIN_COUNT (LAST_PIN - FIRST_PIN + 1)
    
    word timeout[PIN_COUNT]; 
    word elapsed[PIN_COUNT];
    
    void setup() {
      for (byte i = 0; i < PIN_COUNT; i++) {
        timeout[i] = 1000;
        elapsed[i] = 0;
      }
    
      for (byte i = FIRST_PIN; i <= LAST_PIN; i++) {
        pinMode(i, OUTPUT); 
        pinMode(i + PIN_COUNT, OUTPUT);
      }
      
      Serial.begin(9600);
    }
    
    void loop() {
      if (Serial.available() > 0) {
        char x = Serial.read();
        
        if ((x >= 'a') && (x < ('a' + PIN_COUNT))) {
          byte index = x - 'a';
          byte pin = index + FIRST_PIN;
          elapsed[index] = timeout[index];
          digitalWrite(pin, HIGH);
        } else if ((x >= 'A') && (x < ('A' + PIN_COUNT))) {
          byte index = x - 'A';
          byte pin = index + LAST_PIN + 1;
          digitalWrite (pin, !digitalRead(pin));
        }
      }
    
      delay(1);
      for (byte index = 0; index < PIN_COUNT; index++) {
        if (elapsed[index]) {
          if (--elapsed[index]) {
            char pin = index + FIRST_PIN;
            digitalWrite(pin, LOW);
          }
        }
      }
    }
    


    Не проверял но общий смысл думаю понятен.


  1. stDistarik
    27.07.2017 04:56

    Почему не использовали switch() case:?


  1. Hellsy22
    27.07.2017 13:12

    Автор, это элементарная задача даже по меркам старших классов средней школы. Вы выбрали максимально громоздкий и чудовищно неудобный путь. Даже если бы у вас номера пинов шли не подряд, то следовало бы занести их в массив и обращаться к элементам массива. А уж в данном-то случае все вообще тривиально.

    Надеюсь, что статьи программистов о разводке плат выглядят не так жалко и беспомощно…


  1. genk
    27.07.2017 13:54

    Если есть возможность менять клиентский код, то можно просто было воспользоваться firmata для таких целей.
    С ней вообще не надо писать firmware, только client code. А вот его можно писать на любом языке почти, там куча реализаций библиотек протокола.


  1. old_gamer
    27.07.2017 15:29

    можно еще все из-под условий в отдельные фунции выделить:

    // установить а
    long set_a() {
      ledState_a = true;
      time_a = TIME_a;
      return 0;
    }
    
    //...
    
    void loop() {
    
      //...
    
      //a
      if(x == 'a'){
        set_a();
        x = 0;
      }
    
      // ...
    
    }
    


    для каждой проверки отдельную функцию, само собой.


  1. n1tra
    27.07.2017 15:56

    Настоящий китайский код :)