//////////////////Relay//////////////////////////////////
const int relay = 5;
int relayVal;
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//////////////////loadCell///////////////////////////////
#include “HX711.h”
#define zero_factor 555230
#define DOUT 3 //gelb / yellow
#define CLK 2 //orange
float calibration_factor = ((200000 * 0.00045359237) + 52400);
HX711 scale(DOUT, CLK);
float valueReadLoadCell;
float valueLimit;
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//////////////////Servo//////////////////////////////////
#include <Servo.h>
Servo myservo360; // continious rotation servo
Servo myservo180; // 180 servo
int direction;
int pos3 = 0;
//int pos1 = 110;
const int servPin360 = 9;
int speed = 94; // number < 90: movement clockwise; number > 90: movement counterclockwise; the actual number controles the speed of rotation
const int servPin180 = 8;
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
////////////////Button///////////////////////////////////
const int butPin = 12;
int butVal;
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
///////////////Raspberry/////////////////////////////////
char receivedChar; //
boolean newData = false;
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
long firstMeasure = 0;
long secondMeasure;
long interval = 7000;
unsigned long previousMillis = 0;
//_________________________________________________________________________________________
//——————————————-SETUP—————————————–
void setup() {
pinMode(butPin, INPUT);
pinMode(relay, OUTPUT);
Serial.begin(9600);
scale.set_scale(calibration_factor); // when u open the serial monitor the value should be between -0.5 and + 0.5: for setting it to 0 we will have to mount it to the box
scale.set_offset(zero_factor); // Zero out the scale using a previously known zero_factor
Serial.println(“Reading: “);
delay(5000);
valueReadLoadCell = (scale.get_units()); // get the initial value of the load cell into the variable. has to happen once in the setup otherwise the first calculation will be 0 + the interval
}
//________________________________________END of SETUP_____________________________________
//——————————————-LOOP—————————————–
void loop() {
recvInfo();
Serial.print(“Loop: “);
Serial.println(scale.get_units()); // keeps spamming the actual value of the loadCell. should be commented out if the connection is through the pi
checkButton(); // function to check if the button is pressed
if (butVal == HIGH) {
Serial.println(“called through button”);
cButton();
}
if (newData == true) { // if there is the right input data received from the raspberry PI, then start running the system
Serial.println(“called through PI”);
cPI();
}
else {
digitalWrite(relay, HIGH); // disconnect powersupply
relayVal = HIGH; // relay works inverse: HIGH = power gets disconnected from system; only the red led on relay is on
}
}
//_____________________END of LOOP_____________________________________________
//———————FUNCTIONS———————————————–
void recvInfo() { // checks if data is received from the raspberry pi
if (Serial.available() > 0) {
receivedChar = Serial.read(); // puts the value into ther variable receivedChar
if (receivedChar = ‘s’) { // if the value equals s (start)
newData = true; // set new data to true, so that the function of starting the system in the loop can get called
}
else {
newData = false; // if its not a s (start) then do nothing
}
}
}
void cButton() {
wholeSystemFunction(valueReadLoadCell, valueLimit ); // calls the function of starting the sytem started by the button
}
void cPI() {
wholeSystemFunction(valueReadLoadCell, valueLimit); // calls the function of starting the sytem started by the pi
newData = false; // after running the system, the variable has to be set to false again
delay(1000); // give time to process: found out during testing that without its more liable for mistakes
}
void wholeSystemFunction(float valueReadLoadCell, float valueLimit) {
delay(1000);
myservo360.attach(servPin360); // attach the servo that presses the toothpaste
delay(500);
digitalWrite(relay, LOW); // relay works inverse: LOW = connected to external powersupply; red and green led on relay are on
relayVal = LOW; // set the value to its start state with which the servos gets controlled
checkLoadCell(); // check the measured value on the load cell
calcNewValue(valueReadLoadCell, valueLimit); // call the function to calculate a new value
//PUSH TOOTHPASTE
if (relayVal == LOW) { // run following if the relay is on
delay(1000);
Serial.print(“In whole System Function: “);
Serial.println(valueLimit);
previousMillis = millis();
while (scale.get_units() <= valueLimit && millis() – previousMillis <= 8000) { // keep the servo running as long as the measured value, which is changing all the time, is smaller then the interval (one portion of toothpaste). stop moving if the weight is not reached within 8 seconds.
servo360(speed, valueReadLoadCell); // call function to move the servo
}
while (scale.get_units() <= valueLimit && millis() – previousMillis >= 8000) {
return;
}
myservo360.detach(); // detach the servo to stop it from twitching
delay(100);
//OPEN DOOR
myservo180.attach(servPin180); // connect the second servo
servo180(); // call the function of the second servo to open the door
myservo180.detach(); // detach the servo to stop it from twitching
}
}
int checkButton() { // gets called in the loop
butVal = digitalRead(butPin); // put the state of the button into the butVal variable
return butVal; // return the value
}
int checkLoadCell() { // function gets called in wholeSystem function
valueReadLoadCell = (scale.get_units()); // stores the value of the load cell in this variable
Serial.print(“Measured Value in loadCell Function: “);
Serial.println(valueReadLoadCell);
return valueReadLoadCell; // returns the value. this is now a fixed value, which is used in the next function
}
float calcNewValue (float & valueReadLoadCell, float & valueLimit) { //calculate a new variable depending on the measured value + a preset interval
valueLimit = valueReadLoadCell + 0.3; // this variable is very important. the load cell is very responsive, so from one go to the next the number levels in at different values. befor the measured value was compared to a fixed number but since the measured value was not stable at all that was a huge liability and the limit value had to be changed all the time. now the servo rotates on base of a not changing interval and not on a uncontrolable difference.
Serial.print(“Value calculated in calc Function: “);
Serial.println(valueLimit);
return valueLimit;
}
void servo360(int speed, float valueReadLoadCell) {
myservo180.attach(servPin180); // connect the door opener. necesserary because it always twitches open
myservo180.write(110); // set him to 110 degree, which is the closed position. could be set as a variable
delay(100); // give him time to do that
myservo180.detach(); // detach him to stop it from twitching
delay(1000); // give him time to do that
myservo360.write(speed); // start to push toothpaste
}
void servo180() {
open(); // call function to open the box
while (scale.get_units() < 15) { // do nothing as long as the weight recognised is smaller then 50 (we still need to find out which number actually makes sense through making a few measurements when the toothbrush gets put into the bracket, thats the number we need here)
Serial.println(scale.get_units());
}
while (scale.get_units() > 15) { // call function close, when toothbrush gets put into the bracket / box
close();
}
}
void open() {
delay(5000); // this delay gives the toothpaste a little bit time to settle onto the toothbrush
direction = 1; // 1 equals opening direction = clockwise
if (direction == 1) { // if it is one
for (int i = 115; i >= 30; i–) { // move the servo from its starting position to the open position at 30 degree. can be opened further but 30º is enough
myservo180.write(i); //
delay(50); // delay determines the speed of opening the door
}
}
}
int close() {
delay(5000); // this delay is very important, it should be as accurate as possible and be the average time that a person needs to put the toothbrush back into the bracket, and remove his hand, so that the door doesnt close if the hand is still in the door
direction = 0; // 0 equals closing direction = counter clockwise
if (direction == 0) { // if it is zero
for (int i = 30; i <= 115; i++) { // move the servo from its opening position to the close position to 115 degree. the closing position was determined through various tests
myservo180.write(i);
delay(50); // delay determines the speed of opening the door
}
}
return newData = false; // set newData to false, again. probably redundant
delay(5000); // give time to settle
}