Встретил я как-то пост от ClusterM где он сделал виджет в виде старых индикаторов. Мне эта идея безумно понравилась так как есть приятное чувство винтажа в этом проекте. Но вот незадача — я никогда не работал с самим микроконтроллером и программирую я так себе, поэтому идею долго откладывал. Но недавно я натолкнулся на видео где Алекс доработал с помощью знакомых Open source программу и разработал алгоритм обработки данных со стороны Ардуино. В этой статье я хочу показать как я реализовал эту задачу.
Этап I. Как я разбирался с кодом монитора загрузки
После скачивания программы мониторинга я подключил ардуино с дисплеем, в которую был зашит код из библиотеки примеров analogRead, он просто выводит все, что получает ардуино по ком порту. Как можно увидеть я получил массив символов, сначала я экспериментальным путем старался понять, но потом плюнул решил поступить профессиональнее и открыл с помощью ридера кода предоставленный исходник. С помощью я нашел часть которая отправляет все данные в виде массива, для своего удобства выписал их на бумажку, так как код дописывал Алекс с его командой я ничего не менял, а просто взял значения загруженности процессора, видеокарты, и RAM, это значения PCdata[4], PCdata[5], PCdata[6]. После этого я смог дальше работать только с Ардуино.
Этап II. Разбираемся с парсингом данных и их обработкой
Честно говоря, я бы не сказал, что я разобрался, в стиле начинающего гика я просто понял, что код, написанный Алексом, нужен мне без доработок, поэтому я добавил его в свой код. Парсинг выглядит так:
while (Serial.available() > 0) {
char aChar = Serial.read();
if (aChar != 'E') {
inData[index] = aChar;
index++;
inData[index] = '\0';
} else {
char *p = inData;
char *str;
index = 0;
String value = "";
while ((str = strtok_r(p, ";", &p)) != NULL) {
string_convert = str;
PCdata[index] = string_convert.toInt();
index++;
}
index = 0;
isDataExist = true;
}
}
}
Для пущей уверенности через команду lcd.Write я поочередно выводил значения PCdata[4], чтобы убедиться, что принимаю те данные, которые мне нужно.
Дальше я занялся переводом данных в процентах в шим сигнал. Зная, что шим сигнал это значения от 0 до 255, а принимаем мы значения от 0 до 100 (это загруженность в процентах) с помощью функции map и ограничение значений с помощью функции constrain, пишу простой код:
cpu = map(cpu, 0, 100, 0, 255);
cpu = constrain(cpu, 0, 255);
analogWrite(9, cpu);
gpu= PCdata[5];
gpu = map(gpu, 0, 100, 0, 255);
gpu = constrain(gpu, 0, 255);
analogWrite(3, gpu);
mem= PCdata[6];
mem = map(mem, 0, 100, 0, 255);
mem = constrain(mem, 0, 255);
analogWrite(5, mem);
Этап III. Как подключить 3 индикатора к одной ардуино?
Когда я только начинал — я подключал только один индикатор и так действительно все прекрасно, но как только появляется второй — начинаются проблемы. Ардуино не может "раскачать" два вместе, я подозреваю, что это из-за платы ардуино, там очень много вещей которые жрут потребляют энергию (всякие светодиоды, стабилизаторы, защиты от дураков итд) если использовать как ClusterM саму Атмегу — должно хватить, на два уж точно. Я решал проблему с помощью мосфет транзисторов, у меня был IRF520 на плате-конструктор с АлиЭкспресс, подключил один индикатор через мосфет а второй напрямую в ардуино и все заработало. Так как плата с Али чрезмерно огромна, решил паять сам, разводить плату не хотел совсем, поэтому рисовал маркером по текстолиту.
Вышло компактно, а для меня это главное.
Схема подключения такая же как и у платы с Али, ну почти, я убрал светодиод так-как индикация работы тут не нужна.
Этап IV. Дизайн задников для индикатора
Специально сохранял свой дизайн для публикации, но конечный эскиз я успешно потерял, но остался увеличенный прототип. Позже я понял, что это не большая проблема, так как надо будет подгонять к размером ваших индикаторов, я делал в paint photoshop 2020, поэтому уверен, что доработать сможете и вы.
Мне кажется, что вышло очень интересно, осталось вырезать место для саморезов и стрелочки — готово!
Этап V. Подсветка RGB
Так как я в процессе понял, что мне некуда впихнуть светодиод — в итоге я отказался, но начальный код сделал, он очень простой — справится каждый, просто дописать для всех цветов для трех индикаторов. Проектировал на бредборде — работает как часы:
void led()
{
if (PCdata[4] < 20 )
{
digitalWrite (6, HIGH);//например, на этом пине висит зеленая нога rgb
}
else{
digitalWrite (6, LOW);
}
if (PCdata[4] > 20 && PCdata[4] < 60 );//не забываем, что это значения в
//процентах а не значения шим
{
digitalWrite(5, HIGH);//на этом пине - синяя
}
//и так далее для всех светодиодов
}
Итог
Получился интересный виджет, который полезен при играх, редактировании видео и фото так как можно оценить не перегружен ли компьютер.
Совет — старайтесь не ронять ваши индикаторы, у меня случайно упал с RAM и стрелочка не приходит в состояние ноль, оно чинится но это жуткие костыли.
Целый код для ардуино
//#include <Wire.h> // библиотека для соединения
//#include <LiquidCrystal.h>
// оставил с момента отладки, может кому надо будет
//LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char inData[82]; // массив входных значений (СИМВОЛЫ)
int PCdata[20]; // массив численных значений показаний с компьютера
byte index = 0;
String string_convert;
bool isDataExist = false;
int cpu;
int mem;
int gpu;
void setup() {
Serial.begin(9600);
}
void loop() {
parsing();
//led(); для тех кто захочет подключить подсветку
cpu = PCdata[4];
cpu = map(cpu, 0, 100, 0, 255);
cpu = constrain(cpu, 0, 255);
analogWrite(9, cpu);
gpu= PCdata[5];
gpu = map(gpu, 0, 100, 0, 255);
gpu = constrain(gpu, 0, 255);
analogWrite(3, gpu);
mem= PCdata[6];
mem = map(mem, 0, 100, 0, 255);
mem = constrain(mem, 0, 255);
analogWrite(5, mem);
}
void parsing() {
while (Serial.available() > 0) {
char aChar = Serial.read();
if (aChar != 'E') {
inData[index] = aChar;
index++;
inData[index] = '\0';
} else {
char *p = inData;
char *str;
index = 0;
String value = "";
while ((str = strtok_r(p, ";", &p)) != NULL) {
string_convert = str;
PCdata[index] = string_convert.toInt();
index++;
}
index = 0;
isDataExist = true;
}
}
}
/*void led()
{
if (PCdata[4] < 20 )
{
digitalWrite (6, HIGH);//например на этом пине висит зеленая нога rgb
}
else{
digitalWrite (6, LOW);
}
if (PCdata[4] > 20 && PCdata[4] < 60 );//не забываем, что это значения в процентах, а не значения шим
{
digitalWrite(5, HIGH);//на этом пине - синяя
}
//и так далее для всех светодиодов
}
*/
Программа Мониторинга лежит в архиве у Алекса
Я использовал старую версию, она прекрасно работает, поэтому и вам советую.
Хотел бы выразить благодарности Алексу и его команде за доработку Open Source кода, а также пользователю ClusterM за демонстрацию своего гаджета и моему папе за помощь в дешифровке кода.
Комментарии (30)
DROS
12.11.2018 15:18+1Получился интересный виджет, который полезен при играх, редактировании видео и фото так как можно оценить не перегружен ли компьютер.
Я не стебусь, а просто интересуюсь. Ну вот перегружен комп и что дальше?immaculate
12.11.2018 15:24+1Иногда бывает, что какое-то приложение где-то внутри создает поток с бесконечным busy loop, который отъедает 100% CPU. На ноуте это иногда можно заметить без индикатора по постоянно крутящемуся вентилятору.
Чаще всего это веб-браузер (либо ошибка в коде самого браузера, либо какая-нибудь страница с гигабайтами js-кода, делающего непонятно что 100% времени), либо IDE.
GennPen
12.11.2018 15:40поток с бесконечным busy loop, который отъедает 100% CPU
Он отъест не 100% CPU, а загрузит только одно ядро, что будет примерно 25% общей загрузки при 4-ядерном CPU(без HT).
fedorro
12.11.2018 15:42Ну он ещё может быть и недогружен — и можно запустить ещё одну задачу, например. Ну или выполняется несколько задач и при перегрузке можно одну приостановить. Или видно что память заканчивается и можно выключить одно из приложений. У меня вообще на втором мониторе, когда он свободен, диспетчер задач для этих целей развернут на весь экран — позволяет оптимизировать загрузку ресурсов.
А тут, конечно, не хватает ещё загрузки сети и нагрузки на жесткие диски по отдельности для полного комплекта, но это уже какая-то приборная панель получается)
tchspprt
12.11.2018 15:23+3Аналоговая характеристика «температура» преобразовывается в цифру, отдаётся в другую цифру и преобразовывается обратно в аналог для мониторинга аналоговым индикатором… Киберпанк, который мы заслужили.(с)
gingertorrent Автор
12.11.2018 16:10Я реализовал только процент загрузки, плюс это виджет только для наглядности, это же не научное оборудование, это как раз таки киберпанк который мы заслужили, как мне кажется
tchspprt
12.11.2018 16:26+1Я и не критикую :)
«Just for fun» неплохо, атмосфера и интерьер очень важны.gingertorrent Автор
12.11.2018 16:31Спасибо, просто я хотел разъяснить, так как люблю когда мне разъясняют :)
c_kotik
12.11.2018 15:32Взять в руки паяльник и начать что то новое для себя это конечно похвально. Но во всём этом полотне меток актуальна только одна лишь Ардуинка. Вот в каком месте раскрывается суть темы "аналоговые вычисления", затронуты любопытные особенности мосфетов, о которых знает далеко не каждый?
gingertorrent Автор
12.11.2018 16:08Хмм, его суть была сделать просто виджет а не рассказать о мосфетах, использовал их так как у них удобное напряжение открытия, я не претендую на то что это лучшее решение, но такое я нашел. Я пробовал сделать это на транзисторах BC547 если я не ошибаюсь так они не корректно отображали
c_kotik
12.11.2018 16:19Вот и зачем тогда статье выставлять эти метки? Давайте тогда уж засунем туда «резисторы, проводники...» и прочее, что на глаза попало.
И что бы донести претензию к оформлению окончательно, переходя по метке этих несчастных аналоговых вычислений, ожидалось увидеть статью уровня
https://habr.com/post/132702/
, не меньше.gingertorrent Автор
12.11.2018 16:30Cпокойствие, скажу честно я не помню чтобы осознано это вставлял, уже убрал
gingertorrent Автор
12.11.2018 16:14+1слово аналоговый я использовал не в том смысле, может плохо выбрал слово(хотел сказать что это реальное приспособление, а не программа), извиняюсь за дезинформацию.
saipr
12.11.2018 19:48Хотел бы выразить благодарности… моему папе за помощь в дешифровке кода.
Папе низкий поклон!
digdream
13.11.2018 13:16еще есть интересная идея — механический счетчик трафика — взять механизм от счетчика воды, убрать крыльчатку (он отлично располовинивается и вся интересующая часть остается в передней половинке), шаговый двигатель (можно попробовать плоский от жесткого диска) укомплектовываем магнитиком и по «тактам» от чего нибудь, что может получать данные о переданных данных толкаем шаговый двигатель заставляя вращаться циферки )
c_kotik
13.11.2018 14:07Вот вы дошутитесь. Будет потом Ростелеком ходить пломбы на интернет-счётчиках проверять!
gingertorrent Автор
13.11.2018 15:41Я видел схему на электросчетчик старого формата, там есть светодиоды который моргает 1000 рыз за киловатт или как то так, а с водой нужно подумать, но интересно !
GennPen
Неужели ардуина не тянет 2-3 индикатора на 2-3 вольта?
c_kotik
Вот после вашего комментария полез искать их потребление. До даташитов не добрался, но если верить
http://go-radio.ru/strelochniy-voltmetr.html
Как то странно выглядит решение браться сразу за мосфеты.
gingertorrent Автор
Может я сам испортил что-то, но я проверял и действительно не тянет (УНО точно не тянет)
walti
Проверьте сопротивление головок.
У головки без шунта ток полного отклонения до 200 микроАмпер.
От тока GPIO стрелка должна биться об ограничитель так, что ее деформирует.
GennPen
Ардуина Уно тянет в сумме на выходах 40 мА (если не изменяет память), что предостаточно для работы с полсотни вольтметров(если бы хватало выходов).
Может у вас индикаторы не вольтметры, а амперметры? (какое сопротивление головок показывает тестер?)
Когда вы подключали напрямую в ардуину, то использовали общий минус или общий плюс? Если общий плюс, то куда его подключали: на входные 5 В или 3.3 В с ардуины?
gingertorrent Автор
Я подключал минус к gnd а плюс к шим выводу Ардуино, сопротивление не замерял, приду домой — замерю
c_kotik
Может стоит добавить конденсатор параллельно вольтметру? И постараться увеличить частоту ШИМа. Насколько помню, штатно она составляет ~500Гц, что для поставленной задачи может быть маловато.
Ведь данные вольтметры всё таки ориентированны на аналог, а вы ему скармливаете импульсный сигнал довольно низкой частоты.
walti
Может не стоит?
У головки индуктивное сопротивление, ведь там электромагнит, отклоняющий ротор.
И вы лихо предлагает превратить это в параллельный резонансный контур, подключенный напрямую к выходу микроконтроллера.
Правильный вариант — резистор+конденсатор, т.е. классический RC-снаббер, с сопротивлением равнім резистивному сопротивлению головки, и емкостью, обратной индуктивности. Ну и резистор между выходом контроллера и головкой не помешает.
В зависимости от настроек выхода — открытый выход или обоими активными транзисторами, головку цеплять или на землю, или на плюс питания.
Насчет малой частоты — вы видели стрелку, колеблющуюся с частотой 500Гц?
REPISOT
Нужен не снаббер а ФНЧ на RC. Да, это разные схемы.
walti
Сама голова из-за своей механической сути является ФНЧ как минимум первого порядка.
Для ШИМа — нужен именно снаббер.
walti
Это не тот уровень абстракции.
Например, мосфет с затвором, прилепленным напрямую к выходу мк приведет к ВЧ колебаниям. Ибо у проводов индуктивность, а у транзистора — входная емкость.
Туда таки нужен резистор ом на 100, а лучше на Vпитания/Iмаксимальный одного выхода.
Так же и с головкой в стоке мосфета. Если частота станет достаточно высокой, то у вас транзистор пробъет выбросом от закрывания при работе на индуктивность.
Параллельно обмотке головки явно не помешает диод.
Проверьте оммическое сопротивление головки, оно должно быть несколько килоом.
Вы сейчас перезаряжая ломовую входную емкость мосфета в ТО-220 тратите больше энергии, чем на отклонение самой стрелки.