Arduino MU code
// Engine Test Bench - Measuring Unit
// Arduino Uno
// nRF24L01+ (RADIO)
// 10nF capacitor
// HX711 + Load Cell (LC)
// Low Level Trigger Relay (FIRE)
// LCD Keypad Shield (LCD)
#include "HX711.h"
#include <LiquidCrystal.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define CDN_TOTAL_DURATION 6000
#define CDN_MES_START 2000 //When CountDowN reaches CDN_MES_START, measurement starts
#define LED_PIN A1
#define FIRE_PIN 2
#define FIRE_DURATION 1000
#define MES_INTERVAL 25
#define BLINK_INTERVAL_CDN 250
#define BLINK_INTERVAL_MES 50
#define LCD_REFRESH 100
//NRF24L01+ config
#define RADIO_PIN_CE A5
#define RADIO_PIN_CSN A4
RF24 radio(RADIO_PIN_CE, RADIO_PIN_CSN);
//Communication constants
#define ETB_DATA_LEN 8 // 4 bytes for (unsigned long)time and 4 bytes for (float)weight
const uint32_t EBT_TIMECODE_START = 4294967281; //0xFFFFFFF1
const uint32_t EBT_TIMECODE_END = 4294967282; //0xFFFFFFF2
const byte addrDtC[5] = {'E','T','B','D','C'}; //Engine Test Bench Data to Computer
const byte addrMes[5] = {'E','T','B','M','U'}; //Engine Test Bench Measuring Unit
const byte RADIO_START[8] = {0xF1,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00}; //
const byte RADIO_END[8] = {0xF2,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00}; //
//LCD config
#define LCD_PIN_RS 8
#define LCD_PIN_EN 9
#define LCD_PIN_D4 4
#define LCD_PIN_D5 5
#define LCD_PIN_D6 6
#define LCD_PIN_D7 7
#define LCD_PIN_BL 10
#define LCD_PIN_INP A0
LiquidCrystal lcd(LCD_PIN_RS, LCD_PIN_EN, LCD_PIN_D4, LCD_PIN_D5, LCD_PIN_D6, LCD_PIN_D7);
//Load Cell config
#define LC_CALIBRATION 212.5 //HX711 calibration
#define LC_PIN_DOUT A3
#define LC_PIN_SCK A2
HX711 scale;
float inWeight = 0;
uint16_t inButton = 0;
bool isCDN = false;
bool isMES = false;
uint32_t tCurrent = 0;
uint32_t timeBlinkInterval = 0;
uint32_t timeFireStart = 0;
uint32_t timeStartMES = 0;
uint32_t timeStartCDN = 0;
uint32_t timeLastMES = 0;
uint32_t timeLastBlink = 0;
uint32_t timeLastLCD = 0;
uint8_t LED_STATE = LOW;
void setup() {
initRadio();
initLED();
initFIRE();
initLC();
initLCD();
radioReadMode();
}
void loop() {
tCurrent = millis();
inButton = analogRead(LCD_PIN_INP);
if( (isCDN or isMES) and (radioStopMes() or isLeft(inButton)) ){
//Finalize measurements
if(LED_STATE == HIGH){
blink();
}
if(isMES or isCDN){
radioWriteMode();
radioSendStop();
radioReadMode();
isMES = false;
isCDN = false;
}
radioReadMode();
updateLCD();
}else if( not(isCDN or isMES) ){
//Initialize Countdown
if( radioStartMes() ){
timeStartCDN = tCurrent;
isCDN = true;
timeBlinkInterval = BLINK_INTERVAL_CDN;
blinkStart();
updateLCD();
}
}else if(isCDN and not(isMES) ){
if( isStartMes() ){
//Initialize measurement
timeBlinkInterval = BLINK_INTERVAL_MES;
isMES = true;
scale.tare();
tCurrent = millis();
timeStartMES = tCurrent;
timeLastMES = tCurrent-MES_INTERVAL;
radioWriteMode();
radioSendStart();
radioReadMode();
updateLCD();
tCurrent = millis();
}
}else if( isCDN and isMES ){
if( isStopCDN() ){
//CountDown is zero
isCDN = false;
fireStart();
updateLCD();
}
}
if( isBlinkTime() ){
blink();
timeLastBlink += timeBlinkInterval;
}
if( isMESTime() ){
//Measurement : data acquisition / transmission
getWeight();
radioWriteMode();
radioSendData(tCurrent-timeStartMES,inWeight);
radioReadMode();
timeLastMES += MES_INTERVAL;
}
if(isStopFire()){
fireStop();
}
if( isLCDTime() ){
if(not(isMES)){
getWeight();
}
updateLCD();
}
}
void updateLCD(){
uint16_t lcdCDN = 0;
uint32_t lcdMES = 0;
uint8_t i = 0;
lcd.setCursor(13,0);
if(isCDN and isMES){
lcd.print("CDM");
}else if(isCDN){
lcd.print("CDN");
}else if(isMES){
lcd.print("Mes");
}else{
lcd.print("SBY");
}
if(isCDN or isMES){
if(isCDN){
lcdCDN = (uint16_t)((timeStartCDN+CDN_TOTAL_DURATION-tCurrent)/100);//Display CDN
}else{
lcdCDN = (uint16_t)((tCurrent-timeStartMES)/100);//Display MES time
}
lcd.setCursor(15,1);
lcd.print(lcdCDN % 10);
lcdCDN = (uint16_t)(lcdCDN/10);
lcd.setCursor(14,1);
lcd.print(".");
i = 0;
while(i<3){
lcd.setCursor(13-i,1);
if(i>0 and (lcdCDN==0)){
lcd.print(" ");
}else{
lcd.print(lcdCDN % 10);
lcdCDN = (uint16_t)(lcdCDN/10);
}
i++;
}
}else{
lcd.setCursor(11,1);
lcd.print(" ");
}
lcd.setCursor(0,1);
lcd.print(" ' . g");
if(inWeight<0){
lcd.setCursor(0,1);
inWeight = -inWeight;
lcd.print("-");
}
lcdMES = (uint32_t)(inWeight*10);
i = 0;
while(i < 8){
lcd.setCursor(8-i,1);
lcd.print(lcdMES % 10);
lcdMES = (uint32_t)(lcdMES/10);
i += 1;
if( (i==1) or (i==5) ){
i+=1;
}
}
timeLastLCD = tCurrent;
}
void getWeight(){
inWeight = scale.get_units();
}
bool isMESTime(){
if(isMES){
return (tCurrent>(timeLastMES+MES_INTERVAL));
}else{
return false;
}
}
bool isLCDTime(){
return (tCurrent>(timeLastLCD+LCD_REFRESH));
}
bool isStopFire(){
if(timeFireStart>0){
return (tCurrent>(timeFireStart+FIRE_DURATION));
}else{
return false;
}
}
bool isStopCDN(){
return (tCurrent>(timeStartCDN+CDN_TOTAL_DURATION));
}
bool isStartMes(){
return (tCurrent>(timeStartCDN+CDN_TOTAL_DURATION-CDN_MES_START));
}
void fireStop(){
timeFireStart = 0;
digitalWrite(FIRE_PIN,HIGH);
}
void fireStart(){
timeFireStart = tCurrent;
digitalWrite(FIRE_PIN,LOW);
}
bool isBlinkTime(){
if(isCDN or isMES){
return ( tCurrent>(timeLastBlink+timeBlinkInterval) );
}else{
return false;
}
}
void blink(){
if(LED_STATE == HIGH){
digitalWrite(LED_PIN,LOW);
LED_STATE = LOW;
}else{
digitalWrite(LED_PIN,HIGH);
LED_STATE = HIGH;
}
}
void blinkStart(){
timeLastBlink = tCurrent;
}
bool radioSendData(long timeCode, float weight){
byte dataTX[8];
uint8_t timeOut = 5;
memcpy(&dataTX[0],&timeCode,4);
memcpy(&dataTX[4],&weight,4);
while(not(radio.write(&dataTX,8)) and (timeOut>0)){
timeOut--;
}
return (timeOut>0);
}
bool radioSendStart(){
byte dataTX[8];
memcpy(&dataTX[0],&RADIO_START[0],8);
uint8_t timeOut = 10;
while(not(radio.write(&dataTX,8)) and (timeOut>0)){
timeOut--;
}
return (timeOut>0);
}
bool radioSendStop(){
byte dataTX[8];
memcpy(&dataTX[0],&RADIO_END[0],8);
uint8_t timeOut = 10;
while(not(radio.write(&dataTX,8)) and (timeOut>0)){
timeOut--;
}
return (timeOut>0);
}
bool isSelect(int val){
return (val<=800) and (val >= 600);
}
bool isLeft(int val){
return (val<=599) and (val >= 400);
}
void initLC(){
scale.begin(LC_PIN_SCK, LC_PIN_DOUT);
scale.set_scale(LC_CALIBRATION);
scale.tare();
}
void initLCD(){
pinMode(LCD_PIN_BL, OUTPUT);
digitalWrite(LCD_PIN_BL,HIGH);
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("Load Bench");
}
void initFIRE(){
pinMode(FIRE_PIN, OUTPUT);
digitalWrite(FIRE_PIN,HIGH);
}
void initLED(){
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN,LOW);
}
void initRadio(){
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.setPALevel(RF24_PA_MAX);
radio.setRetries(1,5); // delay, count
radio.openWritingPipe(addrDtC);
radio.openReadingPipe(1, addrMes);
}
bool radioStartMes(){
if(radio.available()){
uint8_t messRec[ETB_DATA_LEN];
uint32_t messRecDecode;
radio.read(&messRec,ETB_DATA_LEN);
memcpy(&messRecDecode,&messRec[0],4);
return (messRecDecode == EBT_TIMECODE_START);
}else{
return false;
}
}
bool radioStopMes(){
if(radio.available()){
uint8_t messRec[ETB_DATA_LEN];
uint32_t messRecDecode;
radio.read(&messRec,ETB_DATA_LEN);
memcpy(&messRecDecode,&messRec[0],4);
return (messRecDecode == EBT_TIMECODE_END);
}else{
return false;
}
}
void radioReadMode(){
radio.startListening();
}
void radioWriteMode(){
radio.stopListening();
}