//adrian works in this directory at least #include#include #include #define I2C_ADDR 0x27 // <<----- Add your address here. Find it from I2C Scanner #define BACKLIGHT_PIN 3 #define En_pin 2 #define Rw_pin 1 #define Rs_pin 0 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7 int n = 1; //for tachometer float value = 0; int rev = 0; float rpm; unsigned long oldtime = 0; unsigned long time; boolean firstTimeRising = true; const int DELTA = 2;//mn change for display update float oldF = -DELTA - 1; //to trigger change from 0 // used for centrifugationTimeUpdate const float CENTRIFUGATION_TIME_ACCEPTABLE_RANGE_PERCENTAGE = .10;//min rev for centrifugationStartTime update unsigned long centrifugationStartTime = millis(); // //RCF or G-force= 1.12 x R x (RPM/1000)² where radius in mm float EPPENDORF_45_18_11 = 1.12 * 72.5; //18 place fixed angle rotorfor 1.5-2 ml tubes radius =7.3 cm https://www.eppendorf.com/CA-en/centrifuge-speed-calculator/ LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin); void setup() { lcd.begin(16, 2); //initialize LCD attachInterrupt(digitalPinToInterrupt(2), isr, RISING); //attaching the interrupt on 2 only for Nano // Switch on the backlight lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE); lcd.setBacklight(HIGH); lcd.home (); // go home lcd.clear(); lcd.print("Setup Finished"); Serial.begin(9600); while (!Serial); // pinMode(2, INPUT_PULLUP); Serial.println("\nG-Force"); } void loop() { if (oldF < 20) { delay(1000); } else { delay(300);// 1/3 second } //Serial.println("in loop"); //Serial.println(digitalRead(2)); detachInterrupt(0); //detaches the interrupt time = millis() - oldtime; //finds the time float f = (((float)rev * 1000 / time)) ; //calculates rpm if (abs(f - oldF ) <= DELTA) { f = (f + oldF) / 2; } if (rev == -1) { f = 0; time = 0; rpm = 0; } else { rpm = (f * 60); //calculates rpm } lcd.clear(); updateCentrifugationTime(f); oldF = f; updateValue(f); rev = -1; attachInterrupt(); oldtime = millis(); //saves the current time // Serial.println("centrifugationStartTime:"); // Serial.println(centrifugationStartTime); // Serial.println("centrifugationTime:"); Serial.println("rev:"); Serial.println(rev); } void isr() //interrupt service routine { rev++; } void updateValue(float f) { //lcd.clear(); lcd.setCursor(0, 0); lcd.print(calcG(), 0); lcd.print("G "); // lcd.setCursor(0, 1); lcd.print(rpm, 0); //strip decimals lcd.print("RPM "); lcd.print(f, 1); lcd.print("Hz" ); //optional //lcd.print(" s:"); //lcd.print( time); // lcd.print(" s:"); // lcd.print( time); // lcd.print(" r" ); // lcd.print(rev); } void updateCentrifugationTime(float f) { //start block to update centrifugation time. By my definition is the time when f>10 (600RPM)a dn the value of frequency varies less then float rangeDelta = oldF * CENTRIFUGATION_TIME_ACCEPTABLE_RANGE_PERCENTAGE; if (f < 10 || (f < oldF * (1. - CENTRIFUGATION_TIME_ACCEPTABLE_RANGE_PERCENTAGE)) || (f > oldF * (1. + CENTRIFUGATION_TIME_ACCEPTABLE_RANGE_PERCENTAGE))) { centrifugationStartTime = millis(); } float centTime = ((float) millis() - centrifugationStartTime) / 1000; lcd.setCursor(7, 0); if (centTime < 60) { lcd.print(centTime, 0); //in sec lcd.print("s"); //in sec } else { lcd.print(centTime / 60, 0); lcd.print("m"); lcd.print(centTime - 60 * (int)(centTime / 60), 0); lcd.print("s"); } float tempG = calcG(); if (tempG < 1000) { lcd.print(tempG, 0); lcd.print("G"); } else { lcd.print(calcG() / 1000, 0); lcd.print("kG"); } } void attachInterrupt() { attachInterrupt(digitalPinToInterrupt(2), isr, RISING); //attaching the interrupt on 2// only for Nano } float calcG() { return EPPENDORF_45_18_11 * (rpm / 1000) * (rpm / 1000); } // ///////original code from //#include //LiquidCrystal lcd(12, 11, 6, 5, 4, 3); //float value = 0; //float rev = 0; //int rpm; //int oldtime = 0; //int time; // //void isr() //interrupt service routine //{ // rev++; //} // //void setup() //{ // lcd.begin(16, 2); //initialize LCD // attachInterrupt(0, isr, RISING); //attaching the interrupt //} // //void loop() //{ // delay(1000); // detachInterrupt(0); //detaches the interrupt // time = millis() - oldtime; //finds the time // rpm = (rev / time) * 60000; //calculates rpm // oldtime = millis(); //saves the current time // rev = 0; // lcd.clear(); // lcd.setCursor(0, 0); // lcd.print("___TACHOMETER___"); // lcd.setCursor(0, 1); // lcd.print( rpm); // lcd.print(" RPM"); // lcd.print(" "); // attachInterrupt(0, isr, RISING); // //} //original lcd with shield code //void loop() //{ // // Backlight on/off every 3 seconds // lcd.setCursor (0, 1); // go to start of 2nd line // lcd.print(n++, DEC); // lcd.setBacklight(LOW); // Backlight off // delay(3000); // lcd.setBacklight(HIGH); // Backlight on // delay(3000); //}