Arduino Mod for Open Hardware Monitor

A place to showcase LattePanda creations!
Post Reply
User avatar
LNC-SPN
Posts: 24
Joined: Thu May 19, 2016 7:04 pm
Location: Valencia, Spain
Contact:

Thu Nov 02, 2017 12:40 pm

Hi LattePanders!, if you have installed a system fan for your LattePanda (like me) this mod for Open Hardware Monitor its useful to control the fan (Power On when system start - Power Off when system shutdown - Activate by CPU temp)

You can use a Relay or a NPN Transistor (PWM not implemented yet).

Installation
Download the RAR
OpenHardwareMonitor(Arduino Mod).rar
(461.08 KiB) Downloaded 102 times
Uncompress the OpenHardwareMonitor folder to Program Files(x86)

Image

Arduino Setup
Options - Arduino - COM Port (Select your Arduino COM, AUTO by default)
Options - Arduino - Fan Controller - GPIO Pin (Select the Relay or Transistor Pin)
Options - Arduino - Fan Controller - Enable (You can also select "Activate by CPU temp")
(To change the Pin you need to Disable first)

Important= Options - Run On Windows Startup
Optional = Options - Start Minimized
Recomended= View - Show Gadget (select the items from the list (Right click-Show in Gadget)

Image

How it works?
Using the Standard Firmata library from the Arduino Leonardo side and a custom LattePanda Firmata library (only digitalWrite, low CPU usage)

ArduinoCustomFirmata.cs

Code: Select all

using System;
using System.IO.Ports;
using System.Threading;
using System.Linq;

namespace LattePanda.CustomFirmata
{
    class Arduino
    {
        public const byte LOW = 0;
        public const byte HIGH = 1;
        public const byte OUTPUT = 1;

        public Arduino(string serialPortName)
        {
            _arduinoSerialPort = new SerialPort();

            if (serialPortName == String.Empty)
            {
                _arduinoSerialPort.PortName = List().ElementAt(List().Length - 1);
            }
            else { _arduinoSerialPort.PortName = serialPortName; }
            _arduinoSerialPort.BaudRate = 57600;
            _arduinoSerialPort.DataBits = 8;
            _arduinoSerialPort.Parity = Parity.None;
            _arduinoSerialPort.StopBits = StopBits.One;

            Open();
        }
        public static string[] List()
        {
            return SerialPort.GetPortNames();
        }

        public void Open()
        {
            _arduinoSerialPort.DtrEnable = true;
            _arduinoSerialPort.Open();
            Thread.Sleep(1000);
        }
        public void Close()
        {
            if (_arduinoSerialPort.IsOpen == true)
            {
              _arduinoSerialPort.Close();
            }
           
        }
        public void pinMode(int pin, byte mode)
        {
            byte[] message = new byte[3];
            message[0] = (byte)(SET_PIN_MODE);
            message[1] = (byte)(pin);
            message[2] = (byte)(mode);
            _arduinoSerialPort.Write(message, 0, 3);
            message = null;
        }
        public void digitalWrite(int pin, byte value)
        {
            int portNumber = (pin >> 3) & 0x0F;
            byte[] message = new byte[3];

            if ((int)value == 0)
                _digitalOutputData[portNumber] &= ~(1 << (pin & 0x07));
            else
                _digitalOutputData[portNumber] |= (1 << (pin & 0x07));

            message[0] = (byte)(DIGITAL_MESSAGE | portNumber);
            message[1] = (byte)(_digitalOutputData[portNumber] & 0x7F);
            message[2] = (byte)(_digitalOutputData[portNumber] >> 7);
            _arduinoSerialPort.Write(message, 0, 3);
        }

        private const int MAX_DATA_BYTES = 64;
        private const int TOTAL_PORTS = 2;
        private const int DIGITAL_MESSAGE = 0x90; // send data for a digital port
        private const int SET_PIN_MODE = 0xF4; // set a pin to INPUT/OUTPUT/PWM/etc
        private volatile int[] _digitalOutputData = new int[MAX_DATA_BYTES];
        private SerialPort _arduinoSerialPort;
    }
}
Using ArduinoUtilities class that have a loop to know every second the CPU temp, compare to the max temp setted by user and power on or power off the fan.

Code: Select all

using System;
using System.Threading;
using OpenHardwareMonitor.Hardware;
using LattePanda.CustomFirmata;

namespace OpenHardwareMonitor.Utilities
{
    public class ArduinoUtilities
    {
        private Arduino arduino;
        private PersistentSettings settings;
        public string ArduinoPortName = String.Empty;
        public int RelayFanPin;
        public int RelayFanByTemp;
        private bool ArduinoIsOpen;
        public bool RelayFanIsEnabled;
        public bool RelayFanByTempIsEnabled;
        private bool RelayFanIsOn;

        private Thread readCPUtemp = null;
        private volatile bool keepGetCPUtempRunning = true;

        public ArduinoUtilities(PersistentSettings settings)
        {
            this.settings = settings;
            ArduinoPortName = settings.GetValue("ArduinoPortName", (ArduinoPortName));
            RelayFanIsEnabled = settings.GetValue("RelayFanIsEnabled", (RelayFanIsEnabled));
            RelayFanPin = settings.GetValue("RelayFanPin", (RelayFanPin));
            RelayFanByTempIsEnabled = settings.GetValue("RelayFanByTempIsEnabled", (RelayFanByTempIsEnabled));
            RelayFanByTemp = settings.GetValue("RelayFanByTemp", (RelayFanByTemp));

            if (RelayFanIsEnabled == true && RelayFanByTempIsEnabled == true)
            {
                ActivateRelayFanByTemp();
            }
            else
            {
                if (RelayFanIsEnabled == true)
                {
                    RelayFanON();
                }
            }
        }

        private void OpenArduino()
        {
            arduino = new Arduino(ArduinoPortName);
            ArduinoIsOpen = true;
        }
        public void CloseArduino()
        {
            arduino.Close();
            ArduinoIsOpen = false;
        }

        private void GetCPUTemp()
        {
            while (keepGetCPUtempRunning)
            {
                int CPUtemp;
                var myComputer = new Computer { CPUEnabled = true };
                myComputer.Open();

                foreach (var hardwareItem in myComputer.Hardware)
                {
                    hardwareItem.Update();
                    hardwareItem.GetReport();

                    foreach (var sensor in hardwareItem.Sensors)
                    {
                        if (sensor.SensorType == SensorType.Temperature)
                        {
                            CPUtemp = (int)sensor.Value;
                            if (CPUtemp >= RelayFanByTemp)
                            {
                                RelayFanON();
                            }
                            else
                            {
                                RelayFanOFF();
                            }
                        }
                    }
                }

                Thread.Sleep(1000);
            }
        }
        public void ActivateRelayFanByTemp()
        {
            keepGetCPUtempRunning = true;
            if (readCPUtemp == null)
            {
                readCPUtemp = new Thread(GetCPUTemp);
                readCPUtemp.IsBackground = true;
                readCPUtemp.Start();
            }
        }
        public void DeactivateRelayFanByTemp()
        {
            keepGetCPUtempRunning = false;
            readCPUtemp = null;
        }

        public void RelayFanON()
        {
            if (ArduinoIsOpen == false)
            { OpenArduino(); }

            if (RelayFanIsOn == false)
            {
                arduino.pinMode(RelayFanPin, Arduino.OUTPUT);
                arduino.digitalWrite(RelayFanPin, Arduino.HIGH);
                RelayFanIsOn = true;
            }
        }
        public void RelayFanOFF()
        {
            if (ArduinoIsOpen == false)
            { OpenArduino(); }

            if (RelayFanIsOn == true)
            {
                arduino.pinMode(RelayFanPin, Arduino.OUTPUT);
                arduino.digitalWrite(RelayFanPin, Arduino.LOW);
                RelayFanIsOn = false;
            }
        }
        public void Close()
        {
            if (RelayFanByTempIsEnabled == true)
            {
                RelayFanOFF();
                keepGetCPUtempRunning = false;
                readCPUtemp = null;
            }
            if (RelayFanIsEnabled == true)
            {
                RelayFanOFF();
                CloseArduino();
            }
        }
    }
}
Video Demostration: https://vid.me/7lOj5

Testing
Stable on LattePanda 4GB/64GB Z8300 CPU - Windows 10 64 bits Creators Update
Not tested on LattePanda 2GB/32GB Z8300 CPU - Windows 10 32 bits
Not tested on LattePanda 4GB/64GB Z8350 CPU

Feedback is much appreciated.

Credits/Copyright
Michael Möller (http://openhardwaremonitor.org/)
Kevlin Sun (LattePanda.Firmata)
Luis Navarro (LattePanda.CustomFirmata, OHM Arduino Mod)
Attachments
OpenHardwareMonitor_gadget.jpg
OpenHardwareMonitor_gadget.jpg (58.26 KiB) Viewed 2097 times
OpenHardwareMonitor-Arduino.png
OpenHardwareMonitor-Arduino.png (30.02 KiB) Viewed 2097 times
Last edited by LNC-SPN on Fri Nov 03, 2017 6:53 am, edited 1 time in total.

User avatar
LattePanda
Site Admin
Posts: 1909
Joined: Wed Jan 20, 2016 9:09 am

Fri Nov 03, 2017 4:04 am

Wow, thanks for your sharing, Nice! :)
We are the fans of LattePanda ! :lol:

User avatar
LNC-SPN
Posts: 24
Joined: Thu May 19, 2016 7:04 pm
Location: Valencia, Spain
Contact:

Fri Nov 03, 2017 7:01 am

LattePanda wrote:
Fri Nov 03, 2017 4:04 am
Wow, thanks for your sharing, Nice! :)
:) You're allways wellcome

Hope it helps. ;)

User avatar
Coco Xia
Posts: 73
Joined: Wed Aug 02, 2017 8:36 am

Fri Nov 17, 2017 5:52 am

Look's so nice, my fan is running all the time now, i will try it later :)

User avatar
ED209
Posts: 177
Joined: Tue Apr 19, 2016 3:31 pm

Tue Nov 28, 2017 5:49 pm

What!? This's the coolest project, which matches a very common need for LattePanda!
Very coool.

User avatar
Pip
Posts: 1
Joined: Fri Jun 03, 2016 6:01 pm

Fri Jan 12, 2018 11:07 pm

Not being and electronics expert (read I know very basic stuff) I'm interested to know more information about the relay it's self. I'm looking for either an off the self or DIY relay that would easily fit in a metal case. This is the case I bought http://a.co/gipPL3i. nice looking nothing special, Very functional. would anyone care to share some links that would meet my needs, I'm sure others are also interested.

User avatar
LattePanda
Site Admin
Posts: 1909
Joined: Wed Jan 20, 2016 9:09 am

Mon Jan 15, 2018 10:46 am

Hey, you can check here to find if there is the relay suitable to you. :P
https://www.dfrobot.com/search-relay.html
We are the fans of LattePanda ! :lol:

User avatar
Kellman616
Posts: 34
Joined: Fri Feb 24, 2017 7:11 am

Mon Jan 22, 2018 8:37 am

Amazing! Thanks for sharing!! I've already downloaded the software and used on my lattepanda.It's really a useful function!!!
I want use the Open Hardware Monitor to make my own software too. But I can't get the Temperature of the CPU in console. Do you know why?
Here's my code:

Code: Select all

using System;
using OpenHardwareMonitor.Hardware;
using System.Text;
using System.Threading;
namespace VS_ReadCPUTemperature
{

    class Program
    {
        public class UpdateVisitor : IVisitor
        {
            public void VisitComputer(IComputer computer)
            {
                computer.Traverse(this);
            }

            public void VisitHardware(IHardware hardware)
            {
                hardware.Update();
                foreach (IHardware subHardware in hardware.SubHardware)
                    subHardware.Accept(this);
            }

            public void VisitSensor(ISensor sensor) { }

            public void VisitParameter(IParameter parameter) { }
        }
        static void Main(string[] args)
        {
            while (true)
            {
                UpdateVisitor updateVisitor = new UpdateVisitor();
                Computer computer = new Computer();
                computer.Open();
                computer.CPUEnabled = true;
                computer.Accept(updateVisitor);

                for (int i = 0; i < computer.Hardware.Length; i++)
                {
                    
                    if (computer.Hardware[i].HardwareType == HardwareType.CPU)
                    {
                        for (int j = 0; j < computer.Hardware[i].Sensors.Length; j++)
                        {
                            
                            if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                            {
                                if (computer.Hardware[i].Sensors[j].Name == "CPU Package")  
                                    Console.WriteLine("Tem=" + computer.Hardware[i].Sensors[j].Value.ToString());
                            }
                        }
                    }
                }
                computer.Close();
            }
        }
    }
}
:cry:

Post Reply