Помогите свести код к функции
- Войдите на сайт для отправки комментариев
Вс, 05/02/2012 - 22:45
#include <SPI.h> int led = 0; // переменная для вывода на led int val = 0; // переменная для хранения значения входного напряжения int potPin = 2; // потенциометр подключается к 2-му порту //Порт подключенный к ST_CP 74HC595 SS int latchPin = 22; //Порт подключенный к SH_CP 74HC595 SCK int clockPin = 32; //Порт подключенный к DS 74HC595 mosi int dataPin = 33; void setup() { //устанавливаем режим порта выхода pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } void STI () { //устанавливаем LOW на latchPin пока не окончена передача байта digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, highByte(led)); //ввыводим старший байт shiftOut(dataPin, clockPin, LSBFIRST, lowByte(led)); // выводи младший байт //устанавливаем HIGH на latchPin, чтобы проинформировать регистр, что передача окончена. digitalWrite(latchPin, HIGH); } void loop() { val = analogRead(potPin); // считываем значение с потенциометра val = val/4; // конвертируем из 0-1023 к 0-255 if (val>=0 && val<=16) // сравниваем значение потенциометра с диапазоном загорания первого led ( 16=256(max)/16(кол светодиодов)) { led=1; // присваем переменой led значение при котором загорится первый светодиод (0b0000000000000001) STI(); // ввыводим 2 байта } if (val>16 && val<=32) // сравниваем значение потенциометра с диапазоном загорания первого и второго led (32=(256(max)/16(кол светодиодов))*2) { led=3; // присваем переменой led значение при котором загорится первый и второй светодиод (0b0000000000000011) STI(); // ввыводим 2 байта } if (val>32 && val<=48) // сравниваем значение потенциометра с диапазоном загорания первого и второго led (48=(256(max)/16(кол светодиодов))*3) { led=7; // присваем переменой led значение при котором загорится первый и второй светодиод (0b0000000000000111) STI(); // ввыводим 2 байта } if (val>48 && val<=64) // и.т.д { led=15; STI(); } if (val>64 && val<=80) { led=31; STI(); } if (val>80 && val<=96) { led=63; STI(); } if (val>96 && val<=112) { led=127; STI(); } if (val>112 && val<=128) { led=255; STI(); } if (val>128 && val<=144) { led=511; STI(); } if (val>144 && val<=160) { led=1023; STI(); } if (val>160 && val<=176) { led=2047; STI(); } if (val>176 && val<=192) { led=4095; STI(); } if (val>192 && val<=208) { led=8191; STI(); } if (val>208 && val<=224) { led=16383; STI(); } if (val>224 && val<=240) { led=32767; STI(); } if (val>240 && val<=255) { led=65535; STI(); } }
Помогите пожалуйста основной цикл укоротить с помощью переменных и стандартных функций. Это часть проекта цифрового тахометра с светодиодной индикацией. Суть основной функции сводится к тому что значение снятое с потенциометра сравнивается с диапазоном загорания 1, 2, 3 - 16 светодиодов вместе ( от led = 0b00000000 00000001 до 0b11111111 11111111 ).
Как бы это сделать через "for ( ....) "???
Заранее благодарен за помощь
Извините не представился :)
Я новичок. Дня три как получил из Китая Arduino mega 2560 Crazy Kit.....
В планах сделать led подсветку приборной панели Nissan Note с светодиодной индикацией Тахометра, спидометра, топлива и температуры двигателя. Данные планирую снимать с CAN шины автомобиля.
Просмотрел код по диагонали. Первая мысль это значение val делить на 16 и брать только целую часть. В итоге у нас будут значения от 0 до 15. Потом через switch case сравнивать. Должно получиться намного короче
Спасибо. По поводу /16 понял. А вот про switch case прочитал в разделе программирование, но ничего не понял :(. Если не трудно , киньте простенький пример.
http://www.arduino.ru/Reference/SwitchCase
Я это вижу так:
Спасибо, понял. A как быть со значением Led , может тоже как то можно упростить. Там формула получается led = led*2+1, то-есть если в предидущий момент led = 3 (0b00000000 00000011) горит 2 светодиода, то в следующий момент led=3*2+1=7 что в двоичном исчислении = 0b00000000 00000111 .... ну и так далее... может как то через for можно упростить....
А если значение переменной перескочит так, что led должен поменяться с 3 на 15 сразу. Такое может быть?
Я думаю, что скорость считывания значения, будет гораздо быстрее чем падение или повышение оборотов двигателя, тем более что градация на одно деление светодиодом в 500 оборотов.... так что в любом случае светодиоды будут загораться и тухнуть поочереди..... поидеи :)
Вот, сваял тестовый код для проверки моей идеи. Вроде правильно работает. Заливаете в ардуину и открываете сериал монитор. В него вбиваете число, которое получается от деления на 4 (val = val/4;) тоесть от 0 до 255. а в сериал монитор выходит значение val_new которое от 0 до 16 и led которое от 1 до 65535. На красивость кода внимания не обращай, делался по быстрому. Функция serReadInt добавлена чтоб с сериала нормально читалось и для тебя не нужна
А вот и ваша функция уже исправленная. Я думаю должно быть так:
Попробуйте вот такой вариант:
Работает, спасибо :)
Попробуйте вот такой вариант:
Работает:) Именно то что я хотел, коротко, и работает так как надо, единственное что вместо того чтоб вводить еще pos я val изначально поделил на 64 и в 2 строке в скобках 1 поменял на 2, так как при "1" на минимуме ничего не горело т.е. led = 0b 00000000 00000000, a последнее значение было led = 0b 01111111 11111111, т.е. последний светодиод не горел, при значении 2 всё исправилось.
Обьясните как работает??? Плз!!! Дело в том что это сейчас я снимаю показания с потенциометра, а потом мне будут приходить значения оборотов двигателя от 0 до 70000, т.е. диапазон уже другой....
Вот, сваял тестовый код для проверки моей идеи. Вроде правильно работает. Заливаете в ардуину и открываете сериал монитор. В него вбиваете число, которое получается от деления на 4 (val = val/4;) тоесть от 0 до 255. а в сериал монитор выходит значение val_new которое от 0 до 16 и led которое от 1 до 65535. На красивость кода внимания не обращай, делался по быстрому. Функция serReadInt добавлена чтоб с сериала нормально читалось и для тебя не нужна
А вот и ваша функция уже исправленная. Я думаю должно быть так:
Спасибо большое, работает.
Хороший форум, и люди хорошие, отзывчивые. Спасибо
Операция << это побитовый сдвиг.(На английском arduino.cc/en/Reference/Bitshift).
Спасибо step962, я не додумался применить сюда. Замените тогда конструкцию switch case на эту одну строчку led=(2<<pos)-1;
Вкратце: когда pos=0 то: led= (побитовый сдвиг числа 2 на 0 бит)-1. Это: 10 сдвинуть на 0 бит влево, получается 10, тоесть 2 в десятичной системе. Отнимаем единицу и получаем 1.
когда pos=1 то: led= (побитовый сдвиг числа 2 на 1 бит)-1. Это: 10 сдвинуть на 0 бит влево, получается 100, тоесть 4 в десятичной системе. Отнимаем единицу и получаем 3.
И так далее......
Работает:) Именно то что я хотел, коротко, и работает так как надо, единственное что вместо того чтоб вводить еще pos я val изначально поделил на 64 и в 2 строке в скобках 1 поменял на 2, так как при "1" на минимуме ничего не горело т.е. led = 0b 00000000 00000000, a последнее значение было led = 0b 01111111 11111111, т.е. последний светодиод не горел, при значении 2 всё исправилось.
Ну, тогда уж не
led=(2<<pos)-1;
а
led=(1<<(pos+1))-1;
По получаемым результатам это одно о то же, но второй вариант корректнее методологически.
Кстати, если в моем исходном варианте pos вычислять как-то так:
pos=(int)(val/16.0); или
pos=(val+8)/16; (что, в общем, то же самое - сдвиг "шкалы" на половину ее шага)
то можно получить не 16, а 17 состояний индикации - к нынешним [горит 1 ... горит 16] добавится еще состояние "не горит ни один диод" (при значениях val в диапазоне [0...7]).
Обьясните как работает??? Плз!!! Дело в том что это сейчас я снимаю показания с потенциометра, а потом мне будут приходить значения оборотов двигателя от 0 до 70000, т.едиапазон уже другой....
А что там объяснять-то? Первая и третья строчки - как и в предыдущих вариантах. Вторая остается.
Получив в первой строчке ответ на то, в какой диапазон попадает текущее значение val или - другими словами - сколько светодиодов необходимо поджечь, во второй строке выполняем подготовку к поджогу.
Если вы приглядитесь к тому варианту кодов, который выложили на высокий суд форумчан, то увидите, что среди бесчисленных ифов занимаетесь присваиванием переменной led чисел, являющихся последовательными степенями двойки минус 1. От бесчисленных ифов (сравнения на попадание в определенный диапазон) к вычислению номера диапазона вы перешли еще до моей реплики. Осталось значение для led не из списка брать (case {...}), а тоже вычислять.
Одна из арифметических операций, поддерживаемых языком Си (а вслед за ним и Wiring в Arduino IDE) - побитовый сдвиг влево (<<). В справочнике эта операция не упоминается, но тем не менее в языке она присутствует («Ты суслика видишь? — Нет. — И я нет. А он есть!»). В двоичной системе это по существу умножение на 2 (как и в десятичной системе счисления сдвиг на одну позицию влево означает умножение числа на 10).
Теоретические основы разъяснены, закономерность выявлена. Остается воплотить ее в коде:
led=(1<<pos)-1;
1<<pos - вычисляем нужную нам степень двойки (фактически это 2^pos). Каждое из вычисленных таким способом чисел представляет собой единицу со следующими за ней pos-1 нулями. Что получится при вычитании из такого числа одной-единственной единички, вы, наверное, уже догадались.
Фсе.
Ах, да! Как вы, наверное, догадались, есть еще одна операция прямо противоположного назначения - >>.
ЗЫ: прочитал следующие посты - да вам уже, в общем-то, разъяснили политический момент!!! Ну ладно - "Repetitio est mater studiorum".
Уважаемый step962, огромное спасибо за детальное розжовывание :). Именно этого я и хотел, не просто код, а каод который я понимаю и в котором разобрался :). Особено понравилось часть касающаяся математики.... матери всех технических наук :)
Шафер (мрачно и вскакивая)
Мать! Кто сказал «мать»? Прошу не выражаться при новобрачных.
Шафера оттаскивают.
(с) В.В. (но не Путин)
Вопрос не втему, но может подскажет, для atmega 328 можно использовать любой кварц на 16 Mhz ? или какого то определённого типа? Допустим можно ли использовать вот этот : http://datasheet.elcodis.com/pdf/5/1/50138/nx3225sa-16.000000mhz-t1.pdf ?
Вопрос не втему, но может подскажет, для atmega 328 можно использовать любой кварц на 16 Mhz ? или какого то определённого типа? Допустим можно ли использовать вот этот : http://datasheet.elcodis.com/pdf/5/1/50138/nx3225sa-16.000000mhz-t1.pdf ?
http://arduino.ru/forum/obshchii/aruino-pelletnaya-gorelka#comment-5058
т.е. Это даже хорошо ??? :) А 10 pF хватит ? Просто это у друга в конторе, подешевле, + единственый удовлетворяющий по размерам.
Я про ваш резонатор ничего не писал. Я просто сказал что вместо кварцевого можно поставить керамический. В керамическом 30пф.
Возможно 10 пФ будет мало.
Извините за глупые вопросы, но наверно можно поставить дополнительный конденсатор?
Хз. Я не очень хорошо всё знаю. Просто я намучился с кварцевым резонатором и кондерами. И с радостью перешел на керамику.
Спасибо за ответы :) Буду пробовать