Skip to content

Instantly share code, notes, and snippets.

@sobuildit
Created December 15, 2021 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sobuildit/8412b2ebce4db817e12b81b5f6abcaef to your computer and use it in GitHub Desktop.
Save sobuildit/8412b2ebce4db817e12b81b5f6abcaef to your computer and use it in GitHub Desktop.
Preliminary Controller Arduino code
// 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