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)