Arduino Mod for Open Hardware Monitor ( to control a System Fan)

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
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)
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
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.
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(); } } } }
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)