Projects MakingStuff Research Reference
Good SciFi and Fantasy How to Meditate Simple guide to growing mushrooms Grand Conspiracy Theories My debate style Zen FAQ Zen Center of Georgia Home
               


DutyCycle 1.0



//-----------------------------
// Long Cycle PWM Power Controller
//   Will allow a user to use a pot to initialize a cycle time (1/2 to 5 seconds) 
//  then allow them to use the same pot to change the duty cycle within that cycle
//  time. This turns a circuit on and off accordingly.
//
//  This uses A4 as the sensor for the 10K pot input, which is used to compute a
//  percent.
//
//  The output is on control pin 12. Ostensibly to drive an Op Amp, which will drive an
//  SSR.
//
//  Duty cycles less than 50 milliseconds drops the value to zero, to keep the SSR from cycling
//  on too short a pulse width.
//
//    Glenn Murray - 2/1/2019
//

#include 
#include 

#include  


LCD4Bit_mod lcd = LCD4Bit_mod(2); 

// Constants
   // Pins
const int dutyCycleInput_SensorPin = A4;   // select the input pin for the potentiometer
const int ledPin = 13;      // select the pin for the LED
const int ssrCtrlPin = 12;  // select the pin for SSR control output signal

   // Sensor
const long sensorMin =   33; // Min sensor input * 100
const long sensorMax = 1023 - sensorMin; // Max sensor input * 100

   // Time
const long realMaxTime = 5000.0;   // true Max duty cycle
const long cycleTimeMin = 500.0; // Min duty cycle
const long cycleTimeMax = realMaxTime - cycleTimeMin ; // Max duty cycle

const char pc_sign = '%';
const boolean turnOn = true;
const boolean turnOff = false;

char on[1];
char off[1];
char onval[1];

char blanks[16] = "               ";

// Variables
char buff[16];


long cycleTime; // init to one second cycle time
long dutyCycle; // what delay for duty cycle is - as integer
long percent;   // what % delay for duty cycle is - as integer
int n;

void setup() {
  // put your setup code here, to run once:

  on[0]='+';
  off[0]='-';
  
  
  lcd.init();
  lcd.clear();

  int ndx = 0;
  long last_percent = 150;
  dutyCycle = 0;

  // This loop is used to determine the cycle time
  //   After 2.5 seconds with no change, it will drop out of the loop, proceeding to the main processing
  //   loop.
  //
  while (ndx < 25) {
  
     strcpy(buff, blanks);   // Clear buffer
     percent = inputVal();    // Read input, set the percent use
     n = sprintf(buff, " %4ld",percent);  // Write percent to buffer
     buff[n] = pc_sign;                   // Add percent sign after percent value
     
     lcd.cursorTo(1,0);       // Set cursor to LCD first row
     lcd.printIn(buff);      // Write to LCD

     cycleTime = longPercent( percent, cycleTimeMax ) + cycleTimeMin; // Compute cycle time
   
     n = sprintf(buff, " %4ld|%4ld ms", dutyCycle, cycleTime);       // Write cycleTime to buffer, dutyCycle is zero at this point
     lcd.cursorTo(2,0);       // Set cursor to LCD second row
     lcd.printIn(buff);      // Write to LCD
     
     delay(100);              // Delay for 1/10th second

     // Change detection code, if change made, reset exit counter 
     ndx++;
     if (last_percent != percent) 
        ndx = 0;
     last_percent = percent;
  }
  lcd.clear();
}

void loop() {
   
   strcpy(buff, blanks); // Clear buffer at start of loop
   percent = inputVal();  // Input percent of cycleTime to compute dutyCycle
   dutyCycle = longPercent( percent, cycleTime); // Compute dutyCycle
   if (dutyCycle < 50) {  // If less than 50 milliseconds, set to zero
      dutyCycle = 0;
      percent = 0;
   }

   // Prepare buffers to write settings
   lcd.cursorTo(1,0);
   n = sprintf(buff, " %4ld",percent);
   buff[n] = pc_sign;
   lcd.printIn(buff);

   n = sprintf(buff, " %4ld|%4ld ms", dutyCycle, cycleTime);
   lcd.cursorTo(2,0);
   lcd.printIn(buff);

   // On portion of cycle
   if (dutyCycle > 0) {
       pause( percent,turnOn );
   }

   // Off portion of cycle
   if (dutyCycle != cycleTime) {
       pause( percent, turnOff );
   }

}

// Computes percent. Takes number between 0 and 100, then uses that as percentage to compute the percent of value, to return
long longPercent(long per, long val) {
     return (val * per / 100);
}

// Reads sensor, returns number between 0 and 100 
long inputVal() {
  long sensorValue = (analogRead(dutyCycleInput_SensorPin)- sensorMin) * 100; //* 100;
  long rv =  (sensorValue / sensorMax);
  return (rv);
}

// This sets the output to on or off, depending on 'lit' parameter, and pauses for the 'per' parameter (assumes milliseconds).
void pause( long per, boolean lit) {

      long val;                // Computed delay value
      uint8_t sigVal = HIGH;   // Output signal variable - defaults to on

      if (lit) {
        val = dutyCycle;
        onval[0] = on[0];
      }
      else {
        val = cycleTime - dutyCycle; // off time dutyCycle;
        onval[0] = off[0];
        sigVal = LOW;
      }

      // Writes a plus or minus value to LCD depending on if this period is on or off
      lcd.cursorTo(1,14);  // Set to write on first row
      lcd.printIn(onval);

// Debug
//      if (delA != dutyCycle && delA != (cycleTime-dutyCycle)) {     // Debug code
//         lcd.curortTo(1,0);
//         n = sprintf(buff, "Error   ");
//         lcd.printIn(buff);
//         lcd.cursorTo(2,0);  // Set to write on second row
         
//         n = sprintf(buff2, "%5lu / %4lu   ", val, delA);
//         lcd.printIn(buff2);
//         delay (2000);
//      }
      
      digitalWrite(ssrCtrlPin, sigVal);  // Sends SSR output value
      digitalWrite(ledPin, sigVal);      // Sends LED output value  (may be eliminated if output for OpAmp can be co-opted
      delay(val);                        // Pause
}