// libraries import
#include "HX711.h"
// Rotary Encoder:
int pEncCLK = 2;
int pEncDT = 5; // also as interrupt??
int pEncSW = 3; // button -> interrupt
int goalValue = 0;
boolean direction; // true: clockwise, false: counterclockwise
int lastCLK;
int currentCLK;
// Relay
int pRelIn = 4;
// HX711
int pLoadDT = 13;
int pLoadSCK = 12;
int currentWeight;
HX711 scale;
// 7 segment 1
int pSeg1Latch = 10; // STCP
int pSeg1Data = 9; // DS
int pSeg1Clock = 11; //SHCP
// 7 segment 2
int pSeg2Latch = 7;
int pSeg2Data = 6;
int pSeg2Clock = 8;
int digits [10][8]{
// a,b,c,d,e,f,g,.
{0,0,0,0,0,1,0,1}, // 0
{1,0,0,1,1,1,1,1}, // 1
{0,0,1,0,0,0,1,1}, // 2
{0,0,0,0,1,0,1,1}, // 3
{1,0,0,1,1,0,0,1}, // 4
{0,1,0,0,1,0,0,1}, // 5
{0,1,0,0,0,0,0,1}, // 6
{0,0,0,1,1,1,1,1}, // 7
{0,0,0,0,0,0,0,1}, // 8
{0,0,0,0,1,0,0,1} // 9
};
// additional variables
boolean choiceMade = false;
boolean running = false;
boolean start = false;
float timeout = 20*1000;
void setup() {
Serial.begin(9600);
pinMode(pEncCLK, INPUT_PULLUP);
pinMode(pEncDT, INPUT_PULLUP);
pinMode(pEncSW, INPUT_PULLUP);
pinMode(pRelIn, OUTPUT);
pinMode(pLoadDT, INPUT);
pinMode(pLoadSCK, INPUT);
pinMode(pSeg1Latch, OUTPUT);
pinMode(pSeg1Data, OUTPUT);
pinMode(pSeg1Clock, OUTPUT);
pinMode(pSeg2Latch, OUTPUT);
pinMode(pSeg2Data, OUTPUT);
pinMode(pSeg2Clock, OUTPUT);
attachInterrupt(digitalPinToInterrupt(pEncCLK), getEncoderValue, CHANGE);
attachInterrupt(digitalPinToInterrupt(pEncSW), encoderClick, RISING);
scale.begin(pLoadDT, pLoadSCK);
lastCLK = digitalRead(pEncCLK);
DisplayNumber(0);
}
void loop() {
runningRoutine();
}
// Display 1
void DisplayDigitSeg1(int Digit)
{
digitalWrite(pSeg1Latch,LOW);
if ( Digit < 0 || Digit > 9 ) {
for (int i = 7; i>=0; i--) {
digitalWrite(pSeg1Clock, LOW);
digitalWrite(pSeg1Data, LOW);
digitalWrite(pSeg1Clock, HIGH);
}
}
else {
for (int i = 7; i>=0; i--) {
digitalWrite(pSeg1Clock, LOW);
if (digits[Digit][i]==1) digitalWrite(pSeg1Data, LOW);
if (digits[Digit][i]==0) digitalWrite(pSeg1Data, HIGH);
digitalWrite(pSeg1Clock, HIGH);
}
}
digitalWrite(pSeg1Latch, HIGH);
}
// Display 2
void DisplayDigitSeg2(int Digit)
{
digitalWrite(pSeg2Latch,LOW);
if ( Digit < 0 || Digit > 9 ) {
for (int i = 7; i>=0; i--) {
digitalWrite(pSeg2Clock, LOW);
digitalWrite(pSeg2Data, LOW);
digitalWrite(pSeg2Clock, HIGH);
}
}
else {
for (int i = 7; i>=0; i--) {
digitalWrite(pSeg2Clock, LOW);
if (digits[Digit][i]==1) digitalWrite(pSeg2Data, LOW);
if (digits[Digit][i]==0) digitalWrite(pSeg2Data, HIGH);
digitalWrite(pSeg2Clock, HIGH);
}
}
digitalWrite(pSeg2Latch, HIGH);
}
// Convert 2 digit number to the 2 displays
void DisplayNumber(int number) {
if ( number/10 == 0 )
DisplayDigitSeg1(-1);
else
DisplayDigitSeg1(number/10);
DisplayDigitSeg2(number%10);
}
// Rotary encoder changed, get value and change goalValue accordingly
void getEncoderValue() {
choiceMade = true;
currentCLK = digitalRead(pEncCLK);
if (currentCLK != lastCLK) {
if (digitalRead(pEncDT) != currentCLK) {
goalValue ++;
direction = true;
}
else {
direction = false;
if (goalValue > 0)
goalValue--;
}
}
DisplayNumber(goalValue);
}
// button click of encoder, either starts, stops or goes into choice mode
void encoderClick() {
if ( !running && !start && choiceMade ) {
start = true;
}
else if ( !running && !choiceMade ) {
DisplayNumber(goalValue);
choiceMade = true;
}
else {
start = false;
digitalWrite(pRelIn, LOW);
running = false;
}
}
// routine for grinding, depending on start signal, measured weight, stop signal and timeout
void runningRoutine() {
if ( start && !running ) {
detachInterrupt(pEncCLK);
choiceMade = false;
running = true;
float timeStart = millis();
float currentTime = millis() - timeStart;
boolean tOut = false;
digitalWrite(pRelIn, HIGH);
currentWeight = scale.get_value(5)/420*1000;
while ( currentWeight < goalValue && start ) {
currentWeight = scale.get_value(5)/420*1000;
DisplayNumber(currentWeight);
currentTime = millis() - timeStart;
if ( currentTime > timeout ) {
tOut = true;
break;
}
}
start = false;
digitalWrite(pRelIn, LOW);
running = false;
if ( tOut )
breakRun();
DisplayNumber(currentWeight);
attachInterrupt(digitalPinToInterrupt(pEncCLK), getEncoderValue, CHANGE);
}
}
// display the timeout by blinking the display
void breakRun () {
for ( int i = 0; i < 4; i++) {
DisplayNumber(currentWeight);
delay(500);
DisplayDigitSeg1(-1);
DisplayDigitSeg2(-1);
delay(500);
}
}