Implemented Arduino code
This commit is contained in:
commit
1c0ecea038
224
SimulatorFans.ino
Normal file
224
SimulatorFans.ino
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* SimulatorFans
|
||||
* Copyright (c) 2017 Mark van Renswoude
|
||||
* https://git.x2software.net/pub/SimulatorFans
|
||||
*
|
||||
*
|
||||
* Accepts serial commands to control one or more fans using PWM.
|
||||
*
|
||||
* All commands are terminated with a #10 character and are case sensitive.
|
||||
* Values are passed as ASCII text. This makes it easy to test it using the
|
||||
* Arduino's Serial Monitor.
|
||||
*
|
||||
* Baud rate is 19200 by default.
|
||||
*
|
||||
*
|
||||
* Commands:
|
||||
* >Info
|
||||
* Used for validating that the device is actually a SimulatorFans device.
|
||||
* Returns the number of connected fans.
|
||||
*
|
||||
* Example response:
|
||||
* <Info:Fans=2
|
||||
*
|
||||
* >GetFans
|
||||
* Returns the currently set values for all fans.
|
||||
*
|
||||
* Example response:
|
||||
* <GetFans:0,255
|
||||
*
|
||||
* >SetFans:v1,v2,v...
|
||||
* Updates the fan values. Each value ranges from 0 to 255.
|
||||
*
|
||||
* Example response:
|
||||
* <SetFans
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
|
||||
// The number of fans connected. Each fan must connect to it's own
|
||||
// PWM-enabled pin through a transistor (or preferably MOSFET).
|
||||
#define FanCount 2
|
||||
|
||||
// The pin on which each of the fans is connected. The number of
|
||||
// values must be equal to FanCount (not sure why the compiler
|
||||
// doesn't enforce this if FanCount is bigger). The order is
|
||||
// assumed to be left to right. In a setup of more than 180 degrees,
|
||||
// start counting behind the point of view and in a clockwise manner.
|
||||
//
|
||||
// Possibly the PC software could support remapping at some point in the
|
||||
// future as that's easier than recompiling for the Arduino, but I
|
||||
// wanted to keep it simple until then.
|
||||
const byte FanPin[FanCount] =
|
||||
{
|
||||
5,
|
||||
6
|
||||
};
|
||||
|
||||
// When a fan goes from completely off to a value below full, this
|
||||
// determines how long the fan will run on full power before changing
|
||||
// to the actual value, to give it a chance to start up.
|
||||
#define StartingFansTime 200
|
||||
|
||||
|
||||
/*
|
||||
* Actual code. Lasciate ogne speranza, voi ch'intrate.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
byte value;
|
||||
unsigned long startTime;
|
||||
} FanStatus;
|
||||
|
||||
unsigned long currentTime = 0;
|
||||
FanStatus fanStatus[FanCount];
|
||||
|
||||
|
||||
// Forward declarations
|
||||
void handleInfoCommand();
|
||||
void handleGetFansCommand();
|
||||
void handleSetFansCommand();
|
||||
void handleUnknownCommand();
|
||||
|
||||
void checkStartingFans();
|
||||
void setFan(byte fan, byte value);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
memset(fanStatus, 0, sizeof(fanStatus));
|
||||
|
||||
for (byte fan = 0; fan < FanCount; fan++)
|
||||
pinMode(FanPin[fan], OUTPUT);
|
||||
|
||||
// Set up serial communication (through USB or the default pins)
|
||||
// 19.2k is fast enough for our purpose, and according to the ATMega's datasheet
|
||||
// has a low error percentage across the common oscillator frequencies.
|
||||
Serial.begin(19200);
|
||||
}
|
||||
|
||||
|
||||
char command[50];
|
||||
byte commandLength;
|
||||
char* token;
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
currentTime = millis();
|
||||
checkStartingFans();
|
||||
|
||||
if (Serial.available() > 0)
|
||||
{
|
||||
// Try to read a serial command
|
||||
memset(command, 0, sizeof(command));
|
||||
commandLength = Serial.readBytesUntil('\n', command, sizeof(command) - 1);
|
||||
if (commandLength > 0 && commandLength < sizeof(command))
|
||||
{
|
||||
token = strtok(&command[0], ":");
|
||||
if (token != NULL)
|
||||
{
|
||||
if (strcmp(token, ">Info") == 0)
|
||||
handleInfoCommand();
|
||||
else if (strcmp(token, ">GetFans") == 0)
|
||||
handleGetFansCommand();
|
||||
else if (strcmp(token, ">SetFans") == 0)
|
||||
handleSetFansCommand();
|
||||
else
|
||||
handleUnknownCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleInfoCommand()
|
||||
{
|
||||
Serial.write("<Info:Fans=");
|
||||
Serial.print(FanCount);
|
||||
Serial.write("\n");
|
||||
}
|
||||
|
||||
|
||||
void handleGetFansCommand()
|
||||
{
|
||||
Serial.write("<GetFans:");
|
||||
|
||||
for (byte fan = 0; fan < FanCount; fan++)
|
||||
{
|
||||
if (fan > 0)
|
||||
Serial.write(",");
|
||||
|
||||
Serial.print(fanStatus[fan].value);
|
||||
}
|
||||
|
||||
Serial.write("\n");
|
||||
}
|
||||
|
||||
|
||||
void handleSetFansCommand()
|
||||
{
|
||||
for (byte fan = 0; fan < FanCount; fan++)
|
||||
{
|
||||
token = strtok(NULL, ",");
|
||||
if (token == NULL)
|
||||
break;
|
||||
|
||||
int value = atoi(token);
|
||||
|
||||
if (value < 0) value = 0;
|
||||
if (value > 255) value = 0;
|
||||
|
||||
setFan(fan, value);
|
||||
}
|
||||
|
||||
Serial.write("<SetFans\n");
|
||||
}
|
||||
|
||||
|
||||
void handleUnknownCommand()
|
||||
{
|
||||
Serial.write("<Error:unknown command\n");
|
||||
}
|
||||
|
||||
|
||||
void checkStartingFans()
|
||||
{
|
||||
// Check if any of the fans are currently starting up and
|
||||
// have been for at least StartingFansTime
|
||||
for (byte fan = 0; fan < FanCount; fan++)
|
||||
{
|
||||
if ((fanStatus[fan].startTime > 0) &&
|
||||
(currentTime - fanStatus[fan].startTime >= StartingFansTime))
|
||||
{
|
||||
fanStatus[fan].startTime = 0;
|
||||
setFan(fan, fanStatus[fan].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setFan(byte fan, byte value)
|
||||
{
|
||||
if ((fanStatus[fan].value == 0 || fanStatus[fan].startTime > 0) && value > 0)
|
||||
{
|
||||
// Fan was off or still starting up, start with full power to kick it off
|
||||
analogWrite(FanPin[fan], 255);
|
||||
|
||||
if (fanStatus[fan].startTime == 0)
|
||||
{
|
||||
fanStatus[fan].startTime = currentTime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Already running, simply change the speed and reset the start time if necessary
|
||||
fanStatus[fan].startTime = 0;
|
||||
analogWrite(FanPin[fan], value);
|
||||
}
|
||||
|
||||
fanStatus[fan].value = value;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user