Created
January 22, 2017 00:07
-
-
Save mvladic/a1646b103e838df03e1483e9dfaf724d to your computer and use it in GitHub Desktop.
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
#include <SPI.h> | |
#include <stdlib.h> | |
//////////////////////////////////////////////////////////////////////////////// | |
// BOARD | |
const uint8_t PWR_DIRECT = 55; | |
const uint8_t PWR_SSTART = 56; | |
const uint8_t WATCHDOG = 5; | |
const uint8_t BP_SELECT = 9; | |
const uint8_t BP_OE = 10; | |
const uint8_t RTC_SELECT = 8; | |
const uint8_t ETH_SELECT = 11; | |
const uint8_t LCD_CS = 39; | |
const uint8_t TOUCH_CS = 43; | |
void BOARD_setup() { | |
// disable WATCHDOG | |
pinMode(WATCHDOG, INPUT); | |
// Initialize serial communication | |
Serial.begin(9600); | |
// wait until the serial stream is not open | |
while (!Serial); | |
Serial.println("Serial com ready"); | |
// Address issue with lack of proper SPI connection on PCB r1B9 | |
pinMode(50, INPUT); | |
pinMode(51, INPUT); | |
pinMode(52, INPUT); | |
// BP setup | |
pinMode(BP_SELECT, OUTPUT); | |
pinMode(BP_OE, OUTPUT); | |
digitalWrite(BP_SELECT, HIGH); // Deselect TLC5925 | |
digitalWrite(BP_OE, HIGH); // Deselect TLC5925 OE | |
// RTC setup | |
pinMode(RTC_SELECT, OUTPUT); | |
digitalWrite(RTC_SELECT, LOW); // Deselect PCA21125 | |
// ETHERNET setup | |
pinMode(ETH_SELECT, OUTPUT); | |
digitalWrite(ETH_SELECT, HIGH); // Deselect ETHERNET | |
SPI.begin(); // wake up the SPI bus | |
// TFT | |
pinMode(LCD_CS, OUTPUT); | |
digitalWrite(LCD_CS, LOW); // deselect LCD | |
pinMode(TOUCH_CS, OUTPUT); | |
digitalWrite(TOUCH_CS, LOW); // deselect touch | |
// POWER on | |
pinMode(PWR_DIRECT, OUTPUT); | |
digitalWrite(PWR_DIRECT, LOW); | |
pinMode(PWR_SSTART, OUTPUT); | |
digitalWrite(PWR_SSTART, LOW); | |
digitalWrite(PWR_SSTART, HIGH); | |
delay(700); | |
digitalWrite(PWR_DIRECT, HIGH); | |
delay(100); | |
digitalWrite(PWR_SSTART, LOW); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// FAN | |
#define FAN_SPEED 200 | |
#define FAN_SPEED_MEASURMENT_INTERVAL 5000000L | |
#define FAN_NOMINAL_RPM 4500 | |
const uint8_t FAN_PWM_PIN = 6; | |
const uint8_t FAN_SENSE_PIN = 13; | |
enum RpmMeasureState { | |
RPM_MEASURE_STATE_START, | |
RPM_MEASURE_STATE_MEASURE_T1, | |
RPM_MEASURE_STATE_MEASURE_T2, | |
RPM_MEASURE_STATE_MEASURED, | |
RPM_MEASURE_STATE_FINISHED | |
}; | |
unsigned long FAN_usecLastMeasured; | |
volatile int FAN_rpm; | |
volatile unsigned long FAN_rpmMeasureT1; | |
volatile RpmMeasureState FAN_rpmMeasureState = RPM_MEASURE_STATE_FINISHED; | |
int FAN_intNum; | |
volatile unsigned long FAN_interruptCounter; | |
int FAN_dtToRpm(unsigned long dt) { | |
dt *= 2; // duty cycle is 50% | |
dt *= 2; // 2 impulse per revolution | |
return (int)(60L * 1000 * 1000 / dt); | |
} | |
void FAN_startMeasure() { | |
analogWrite(FAN_PWM_PIN, 255); | |
delay(2); | |
FAN_rpmMeasureState = RPM_MEASURE_STATE_START; | |
attachInterrupt(FAN_intNum, FAN_interruptHandler, CHANGE); | |
} | |
void FAN_interruptHandler() { | |
++FAN_interruptCounter; | |
if (FAN_rpmMeasureState != RPM_MEASURE_STATE_FINISHED && FAN_rpmMeasureState != RPM_MEASURE_STATE_MEASURED) { | |
// measure length of the square pulse | |
int x = digitalRead(FAN_SENSE_PIN); | |
if (FAN_rpmMeasureState == RPM_MEASURE_STATE_START && x) { | |
FAN_rpmMeasureState = RPM_MEASURE_STATE_MEASURE_T1; | |
} else if (FAN_rpmMeasureState == RPM_MEASURE_STATE_MEASURE_T1 && !x) { | |
// start is when signal goes from 1 to 0 | |
FAN_rpmMeasureT1 = micros(); | |
FAN_rpmMeasureState = RPM_MEASURE_STATE_MEASURE_T2; | |
} else if (FAN_rpmMeasureState == RPM_MEASURE_STATE_MEASURE_T2 && x) { | |
// stop is when signal goes from 0 to 1 | |
unsigned long rpmMeasureT2 = micros(); | |
int rpm = FAN_dtToRpm(rpmMeasureT2 - FAN_rpmMeasureT1); | |
if (rpm > (int)ceil(FAN_NOMINAL_RPM * 1.05)) { | |
// invalid RPM | |
} else { | |
FAN_rpm = rpm; | |
} | |
FAN_rpmMeasureState = RPM_MEASURE_STATE_MEASURED; | |
} | |
} | |
} | |
void FAN_finishMeasure() { | |
if (FAN_rpmMeasureState == RPM_MEASURE_STATE_MEASURED) { | |
analogWrite(FAN_PWM_PIN, FAN_SPEED); | |
FAN_rpmMeasureState = RPM_MEASURE_STATE_FINISHED; | |
detachInterrupt(FAN_intNum); | |
} | |
} | |
void FAN_setup() { | |
// | |
pinMode(FAN_PWM_PIN, OUTPUT); | |
pinMode(FAN_SENSE_PIN, INPUT); | |
// | |
FAN_intNum = digitalPinToInterrupt(FAN_SENSE_PIN); | |
// set FAN speed | |
analogWrite(FAN_PWM_PIN, FAN_SPEED); | |
} | |
void FAN_tick(unsigned long usec) { | |
if (usec - FAN_usecLastMeasured >= FAN_SPEED_MEASURMENT_INTERVAL) { | |
// start FAN speed measure every 5 seconds | |
FAN_usecLastMeasured = usec; | |
FAN_startMeasure(); | |
} else { | |
// check measurement | |
RpmMeasureState rpmMeasureState = FAN_rpmMeasureState; | |
if (rpmMeasureState == RPM_MEASURE_STATE_MEASURED) { | |
// measurement finished | |
FAN_finishMeasure(); | |
Serial.print("RPM="); | |
Serial.println(FAN_rpm); | |
} else if (rpmMeasureState != RPM_MEASURE_STATE_FINISHED) { | |
// measurement didn't finished in 50ms, declare measurement failure | |
if (usec - FAN_usecLastMeasured >= 50 * 1000L) { | |
// cleanup | |
FAN_rpmMeasureState = RPM_MEASURE_STATE_MEASURED; | |
FAN_rpm = 0; | |
FAN_finishMeasure(); | |
Serial.println("RPM measurement failed!"); | |
} | |
} | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// ADC | |
SPISettings ADS1120_SPI(4000000, MSBFIRST, SPI_MODE1); | |
// ADC PINS | |
const uint8_t ISOLATOR_EN = 14; | |
const uint8_t ADC_SELECT_PIN = 15; | |
const uint8_t ADC_INTERRUPT_PIN = 21; | |
// ADC commands | |
const uint8_t ADC_RESET = 0B00000110; | |
const uint8_t ADC_START = 0B00001000; | |
const uint8_t ADC_RDATA = 0B00010000; | |
// | |
const uint8_t ADC_WR3S1 = 0B01000110; | |
const uint8_t ADC_WR1S0 = 0B01000000; | |
// | |
const uint8_t ADC_REG0_READ_U_MON = 0x91; // B10010001: [7:4] AINP = AIN1, AINN = AVSS, [3:1] Gain = 1, [0] PGA disabled and bypassed | |
/// How many times per second will ADC take snapshot value? | |
/// 0: 20 SPS, 1: 45 SPS, 2: 90 SPS, 3: 175 SPS, 4: 330 SPS, 5: 600 SPS, 6: 1000 SPS | |
const uint8_t ADC_SPS = 0; | |
const uint8_t ADC_REG1_VAL = (ADC_SPS << 5) | 0B00000000; | |
const uint8_t ADC_REG2_VAL = 0B01100000; // Register 02h: External Vref, 50Hz rejection, PSW off, IDAC off | |
const uint8_t ADC_REG3_VAL = 0B00000000; // Register 03h: IDAC1 disabled, IDAC2 disabled, dedicated DRDY | |
volatile int ADC_interruptHandlerCounter; | |
void ADC_start() { | |
SPI.beginTransaction(ADS1120_SPI); | |
digitalWrite(ISOLATOR_EN, HIGH); | |
digitalWrite(ADC_SELECT_PIN, LOW); | |
SPI.transfer(ADC_WR1S0); | |
SPI.transfer(ADC_REG0_READ_U_MON); | |
SPI.transfer(ADC_START); | |
digitalWrite(ADC_SELECT_PIN, HIGH); | |
digitalWrite(ISOLATOR_EN, LOW); | |
SPI.endTransaction(); | |
} | |
int16_t ADC_read() { | |
SPI.beginTransaction(ADS1120_SPI); | |
digitalWrite(ISOLATOR_EN, HIGH); | |
digitalWrite(ADC_SELECT_PIN, LOW); | |
// Read conversion data | |
SPI.transfer(ADC_RDATA); | |
uint16_t dmsb = SPI.transfer(0); | |
uint16_t dlsb = SPI.transfer(0); | |
digitalWrite(ADC_SELECT_PIN, HIGH); | |
digitalWrite(ISOLATOR_EN, LOW); | |
SPI.endTransaction(); | |
return (int16_t)((dmsb << 8) | dlsb); | |
} | |
void ADC_interruptHandler() { | |
++ADC_interruptHandlerCounter; | |
int16_t adc_data = ADC_read(); | |
// ... | |
ADC_start(); | |
} | |
void ADC_setup() { | |
// | |
pinMode(ADC_SELECT_PIN, OUTPUT); | |
digitalWrite(ADC_SELECT_PIN, HIGH); // Deselect ADS1120 | |
// | |
int intNum = digitalPinToInterrupt(ADC_INTERRUPT_PIN); | |
SPI.usingInterrupt(intNum); | |
attachInterrupt(intNum, ADC_interruptHandler, FALLING); | |
// Send RESET command | |
SPI.beginTransaction(ADS1120_SPI); | |
digitalWrite(ISOLATOR_EN, HIGH); | |
digitalWrite(ADC_SELECT_PIN, LOW); | |
SPI.transfer(ADC_RESET); | |
delayMicroseconds(100); // Guard time | |
SPI.transfer(ADC_WR3S1); | |
SPI.transfer(ADC_REG1_VAL); | |
SPI.transfer(ADC_REG2_VAL); | |
SPI.transfer(ADC_REG3_VAL); | |
digitalWrite(ADC_SELECT_PIN, HIGH); | |
digitalWrite(ISOLATOR_EN, LOW); | |
SPI.endTransaction(); | |
// | |
ADC_start(); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
void setup() { | |
BOARD_setup(); | |
FAN_setup(); | |
ADC_setup(); | |
} | |
unsigned long usecLast = 0; | |
void loop() { | |
unsigned long usec = micros(); | |
FAN_tick(usec); | |
if (usec - usecLast > 1000000UL) { | |
Serial.print("FAN interrupt counter = "); | |
Serial.print(FAN_interruptCounter1); | |
FAN_interruptCounter = 0; | |
Serial.print(", ADC interrupt counter = "); | |
Serial.println(ADC_interruptHandlerCounter); | |
ADC_interruptHandlerCounter = 0; | |
usecLast = usec; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment