[Из песочницы] Аналоговый индикатор загруженности компьютера
Встретил я как-то пост от 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 // библиотека для соединения
//#include
// оставил с момента отладки, может кому надо будет
//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 за демонстрацию своего гаджета и моему папе за помощь в дешифровке кода.