Machine Speed Logger
Records the speeds of machines using arduino, PHP, MySQL, and C#
This whole project takes an arduino mega equipped with a W5500 ethernet shield and a proximity sensor (55505-00-02-A-ND) to count gear teeth pulses, calculates the feet per minute the machine is moving at, sends it to a PHP page hosted on my computer which writes the data to a MySQL database which is then graphed using a program I made in C#. Whew!
The circuit is extremely simple. The prox sensor's black cable goes to ground, red goes to 5V, and the white/black stripped one goes to the interrupt pin on the uno (INT1/digital pin 3).
Credit needs to go where it's due - this tutorial here REALLY helped me out with a lot of the Arduino/PHP stuff! So thank you! :D
For MySQL ... well, it's easy enough to install and all that. I used HeidiSQL to build my table, which has 5 columns:
- id - auto incrementing/primary key/int
- date - a varchar, because working with the Date type pissed me off, lol
- time - a Time
- machine id - int
- speed - double
Nothing terribly complicated there!
I, being totally unaware of what I was doing, bought a W5500 ethernet shield for an Arduino Uno from digikey. This would prove to be the first wrench thrown in my path - I couldn't get any of those darned Ethernet examples to work! The problem ended up being that I needed to replace the ethernet library with the one found at this link here. There are some instructions on that page to help you with this, too!
The arduino sketch was not terribly complicated. I used an interrupt to count the pulses from the proximity sensor (part number 55505-00-02-A-ND on digikey) and, every 5 seconds in this example (interval), figure out the fpm by calling CheckInterval() and then use the ethernet shield to send it to a PHP page hosted on my computer. The pressid variable will be different depending on which machine we are recording so we can differentiate them in the table later.
Here's my Arduino code:
// Gear Tooth Counter // http://r.lagserv.net //Include library files #include <SPI.h> #include <Ethernet.h> #include <SD.h> //Variables we actually want control over int pressid = 3; float interval = 30000; //in milliseconds //Initialize global variables volatile long int c = 0; int pressSpeed = 0; unsigned long totalTimeElapsed = 0; unsigned long previousTimeElapsed = 0; float minutes = 0; float feet = 0; float seconds = 0; float inches = 0; float fpm = 0; float inchespersecond = 0; //Setup for Ethernet Library byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; byte server[] = { 192, 168, 1, 107 }; EthernetClient client; //------------------------------------------------------ //ARDUINO SETUP //------------------------------------------------------ void setup() { //Disable SD card if one in the slot pinMode(4,OUTPUT); digitalWrite(4,HIGH); //Setup interrupt for counting gear teeth attachInterrupt(digitalPinToInterrupt(3), pulse, FALLING); //Begin serial Serial.begin(115200); //Wait 15 seconds for the user to connect the ethernet cable delay(15000); //Begin ethernet if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); } //Give ethernet shield a chance to start up delay(1000); } //------------------------------------------------------ //MAIN ARDUINO LOOP //------------------------------------------------------ void loop() { //If the ISR isn't being triggered we still need to record that the press has been stationary if(millis() - previousTimeElapsed > interval + 1000) { CheckInterval(); } } //------------------------------------------------------ //PULSE FUNCTION (ISR) - COUNTS GEAR TEETH //------------------------------------------------------ void pulse() { //Increment the counter variable c++; //Check to see if its time to calculate the press speed CheckInterval(); } //------------------------------------------------------ //CHECKINTERVAL - CHECK TO SEE IF INTERVAL HAS ELAPSED AND CALCULATE AVERAGE PRESS SPEED //------------------------------------------------------ void CheckInterval() { totalTimeElapsed = millis(); //When the interval has elapsed to determine average press speed over that interval if(totalTimeElapsed - previousTimeElapsed > interval) { float teethCounted = c; //Do some math minutes = interval/1000/60; feet = teethCounted/8/12; fpm = feet/minutes; //Print the result Serial.print("Feet per minute: "); Serial.print(fpm); Serial.println(); //Write to MySQL DataToMySql(); //Reset the timer previousTimeElapsed = totalTimeElapsed; //Reset the teeth count c = 0; } } //------------------------------------------------------ //DATATOMYSQL - SEND DATA TO PHP PAGES WHICH IN TURNS ADDS IT TO MYSQL //------------------------------------------------------ void DataToMySql() { //Serial.println("HERE WE GO!"); if (client.connect(server, 80)) { Serial.println("-> Connected"); // Make a HTTP request: client.print( "GET /dbconnect.php?"); client.print("id="); client.print( pressid ); client.print("&&"); client.print("speed="); client.print( fpm ); client.println( " HTTP/1.1"); client.print("Host: "); client.println("192.168.107"); //client.println(server); client.println("Connection: close"); client.println(); client.stop(); } else { // you didn't get a connection to the server: Serial.println("--> connection failed/n"); } }
I really need to preface this by saying this was my first hands-on exposure to PHP, and this step was extremely infuriating as many of the examples I had found online used old, depreciated code. I admit that this is probably far from the best way of doing this ... but hey! It works!
I used WAMPServer to host this file by sticking it in C:\wamp\www
//dbconnect.php <?php $servername = "localhost"; // this is usually "localhost" unless your database resides on a different server $username = "root"; // enter your username for mysql $password = "nintendo"; // enter your password for mysql $dbname = "test"; // Create connection $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } //Grab the current date date_default_timezone_set('America/Los_Angeles'); $date = date('Y-m-d'); $time = date('H:i:s'); // Prepare the SQL statement $sql = "INSERT INTO test.test (date, time, machineid, speed) VALUES ('$date', '$time', '".$_GET['id']."', '".$_GET['speed']."')"; // Execute SQL statement if ($conn->query($sql) === TRUE) { echo "New record created successfully"; } else { echo "Error: " . $sql . "<br>" . $conn->error; } $conn->close(); ?>
Obviously I can't effectively share all my C# code here, and also because I'm hoping to possibly sell this, I'll keep my code mostly to myself (muahahaha!). However, here is a picture of the program thus far. It allows you to graph up to 4 different machines in real-time. You can also change the dates of the individual series on the graph so you can compare the same or different presses on the same or different days! Although comparing the same press on the same day might be a bit silly, but you get the idea. For example, if one press runs a job on September 26 and a different press runs the same job on November 26, you can compare the two! So that's kind of cool.
The max speed in this screenshot is only set to 6 because I was simulating records in the table by tapping the prox sensor against a gear on my desk! However I tried out the arduino sketch beforehand on a machine at work and it counted reliably (and very consistently!) at 150 fpm, which is a pretty standard running speed for the more involved work that we run.