Created
December 15, 2021 14:00
-
-
Save sobuildit/8412b2ebce4db817e12b81b5f6abcaef to your computer and use it in GitHub Desktop.
Preliminary Controller Arduino code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Digital setup | |
#define CH0 3 | |
#define CH1 5 | |
#define CH2 6 | |
#define CH3 9 | |
#define CH4 10 | |
#define CH5 11 | |
#define PWM_IDLE 128 | |
#define PWM_MAX 255 | |
#define INIT_TIME 20000 | |
#define SERIAL_BAUD 57600 | |
#define TIMER_INIT 5000 | |
//#define DEBUG 1 | |
const int channel[6] = {CH0, CH1, CH2, CH3, CH4, CH5}; | |
bool cmdComplete = false; // whether the string is complete | |
char buffer[64]; // Serial comms buffer | |
char *cmdPtr = buffer; // Serial comms buffer pointer | |
void forceAllFansOn(void); // What happens on a comms timeout | |
void setup() { | |
int i; | |
Serial.begin(SERIAL_BAUD); | |
// Crank all the fans up to full wompo before | |
// dropping down to the initial minimum value | |
// after init. The fans are slow to respond, | |
// so we need to wait around a bit. | |
for (i=0;i<6;i++){ | |
pinMode(channel[i], OUTPUT); | |
analogWrite(channel[i], PWM_MAX); | |
} | |
delay(INIT_TIME); | |
for (i=0;i<6;i++){ | |
analogWrite(channel[i], PWM_IDLE); | |
} | |
} | |
void loop() { | |
int ch, pwm; | |
char cmd, c; | |
int timer = TIMER_INIT; // if timer gets to zero, forceFull is triggered | |
bool forceFull = false; // force all fans to 100% | |
bool doCmdLoop = true; | |
// read-process loop | |
// Suck strings from the host of the form: | |
// | |
// PWM Set | |
// Command: S n:p, n:p, ... where n=0..5 selects a fan, | |
// and value P=0..255 programs the PWM duty | |
// Reponse: OK | |
// | |
// Ping / Keepalive | |
// Command: P | |
// Send a keealive command, resets the connection timeout | |
// If timeout is exceeded, max PWM mode is triggered, which | |
// sets all fans to max | |
// Response: OK | |
// | |
Serial.println("PWM Controller ready"); | |
cmdPtr = buffer; | |
while (1) { | |
while (Serial.available()) { | |
char inChar = (char)Serial.read(); | |
*cmdPtr++ = toupper(inChar); | |
if (inChar == '\n'){ | |
*cmdPtr++ = 0; | |
cmdComplete = true; | |
cmdPtr = buffer; | |
} | |
} | |
if (cmdComplete){ | |
cmdComplete = false; | |
#ifdef DEBUG | |
Serial.print(">>"); | |
Serial.print(buffer); | |
Serial.println("<<"); | |
#endif // DEBUG | |
// Yank off the command char | |
cmd = *cmdPtr++; | |
switch(cmd){ | |
case 'S': // Set | |
timer = TIMER_INIT; | |
forceFull = false; | |
doCmdLoop = true; | |
// iterate the fan set list (it may be sparse) and program the fans | |
// pull off a fan:pwm value pair, then look for another comma separator and iterate if found | |
while(doCmdLoop){ | |
sscanf(cmdPtr, "%d:%d", &ch, &pwm); | |
// validate values and ignore if out of bounds | |
if (ch >= 0 and ch <= 5){ | |
if (pwm >= 0 and pwm <= 255){ | |
#ifdef DEBUG | |
Serial.print("fan:"); | |
Serial.print(ch); | |
Serial.print(" value:"); | |
Serial.println(pwm); | |
#endif // DEBUG | |
analogWrite(channel[ch], pwm); | |
} | |
} | |
while(1){ | |
c = *cmdPtr++; | |
if (c == '\n'){ | |
doCmdLoop = false; | |
break; | |
} else if (c == ','){ | |
break; | |
} | |
} | |
} | |
Serial.println("OK"); | |
break; | |
case 'P': // Ping | |
timer = TIMER_INIT; | |
Serial.println("OK"); | |
break; | |
} // switch(cmd) | |
cmdPtr = buffer; | |
} // if (cmdComplete){ | |
if (timer){ | |
timer--; | |
} else { | |
forceFull = true; | |
forceAllFansOn(); | |
timer = TIMER_INIT; | |
Serial.println("timeout: forcing 50%"); | |
} | |
delay(1); | |
} // while (1) | |
} | |
void forceAllFansOn(void){ | |
int i; | |
for (i=0;i<6;i++){ | |
analogWrite(channel[i], PWM_IDLE); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment