Pull to refresh

Аналоговый индикатор загруженности компьютера

Reading time 4 min
Views 9.7K

Встретил я как-то пост от 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 за демонстрацию своего гаджета и моему папе за помощь в дешифровке кода.

Tags:
Hubs:
+17
Comments 30
Comments Comments 30

Articles