First let me say I am very very new at Arduino and coding, so hope you guys can help me out with a few things.
With that said, I'm working on a color sorting machine for bottlecaps and I'm having problem with the type of code that I should use for this type of build. I am using a RGB TCS34725 color sensor for color detection and servomotors to move some arms. I will use a conveyor belt to move the bottle caps along the color sensor then to the correct arm for sorting.
I found a code online that kind of work, but because it's an "if else" kind of code with delays I can't made the color detection run constantly since it has to finish the sequences first before it can start with color detection again. So, I don't know if there's a code to fix this or if I need something extra to store the data gather from the color sensor and then use that data to drive the servomotors.
Here is the code I found online and the one I'm using right now
// include libraries
#include "Servo.h"
#include "Wire.h"
#include "Adafruit_TCS34725.h"
// servo positions in degrees for colors, please adjust
const int redPos = 45;
const int bluePos = 45;
const int startPos = -45;
// initialize servo object
Servo myservo;
// Initialize Color Sensor object
// For parameters see: https://learn.adafruit.com/adafruit-color-sensors/program-it
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_1X);
// setup() is executed once when the Arduino starts up
void setup() {
// Serial communication to output the value in the serial monitor
Serial.begin(9600);
Serial.println("Makerblog.at - MuMs Color Sensor");
// Check if Color Sensor reports back
if (tcs.begin()) {
// Everything OK
Serial.println("Sensor found");
} else {
// No sensor found. Freeze program at this point
Serial.println("TCS34725 not found... process stopped!");
while (1)
; // Stop!
}
// The servo hangs on the PWM pin 3
myservo.attach(3);
// Move servo to home
myservo.write(0);
delay(100);
myservo.attach(4);
// Move servo to home
myservo.write(0);
delay(100);
}
// loop() is repeated as long as the Arduino is running
void loop() {
// The sensor returns values for R, G, B and a clear value
uint16_t clearcol, red, green, blue;
float average, r, g, b;
delay(60); // color measurement takes c. 50ms
tcs.getRawData(&red, &green, &blue, &clearcol);
// My attempt at color identification for
// the 5 M&M colors red, green, blue, orange and yellow
// average RGB
average = (red + green + blue) / 3;
// color values by average,
// all values are now hovering around 1
r = red / average;
g = green / average;
b = blue / average;
// Output clear value and r,g,b serially to check
// r,g and b should be between approx. 0.5 and
// 1.5. If the sensor sees red, then r should be well above 1.0
//, g and b between 0.5 and 1.0, etc.
Serial.print(" \t Red:");
Serial.print(r);
Serial.print(" \t Blue:");
Serial.print(b);
// Attempt to find color based on r,g,b values.
// It's best to start with red, green, blue
//and adjust the thresholds accordingly // with the serial output
if ((r > 1.4) && (g < 0.9) && (b < 0.9)) {
delay(5000);
myservo.attach(4);
Serial.print("\t RED");
myservo.write(redPos);
delay(500);
myservo.write(startPos);
}
else if ((r < 0.8) && (g < 1.2) && (b > 1.2)) {
delay(500);
myservo.attach(3);
Serial.print("\t BLUE");
myservo.write(bluePos);
delay(500);
myservo.write(startPos);
}
// If no rule applies, then be honest
else {
Serial.print(" \t NOT RECOGNIZED");
// myservo.write(nonePos);
}
// print newlines
Serial.println("");
// Adjust wait time for serial debugging
delay(100);
}
Split the project into smaller parts,
Focus on reading the colour sensor. When that works add some servo testing code.
Go on like that and tune the different parts together.
What works and what is the closest obstacle.
You have to get rid of any 'delay()' operations if you want continuous detection of color.
Do the servos knock the caps off the conveyor or put a diverter in place so that the cap falls off the side as the conveyor moves? Either will need to be timed based on the speed of the conveyor. Is the conveyor running at a fixed speed?
Something else that will give you extra time is a mechanical means of creating distance between each of the elements you are checking for color, one way would be to have two conveyors with the downstream conveyor runnning a little faster than the first conveyor so that a gap was created as each element hit the second conveyor, a second method is to feed the product onto the center of a disk and as they travel to the outer edge of the disk the speed increases and again you get separation. I am sure if you google you will find many similar examples.
So you have caps coming along a conveyor belt. Have the sensor read the colour at one point. Create a queue of colours. Then let the cap fall off from the belt, either at the end of the belt or pushed off by a static obstacle. The cap falls into a tube with a rotating end, which points to the right jar of a circle of jars. You have the queue of colours, so you know all the time where to place the next falling cap. No need to wait at the colour sensor until the previous cap has found its jar. Does that make sense?
So you can read the next cap while the previous cap is still on its way to the tube. The critical point is the mechanism that guides the cap to the right jar. It needs its time to find the right jar before the cap may fall off the belt and into the tube. This might require the belt to stop for a moment.
This could be one of the most interesting projects around here, important even. Have you got anything mechanical to show yet, or are you just establishing the principals?
I think the Arduino is capable of doing the job you want. It doesn't matter which mcu you choose the mechanics are going to be a critical part of the reliability. There are so many ways this can be done that only you can determine with experimentation. Like someone mentioned split it into pieces, start with a feeder or magazine, go on to the conveying system making sure they are right side up, separate and align them for the vision system, run them through the vision system perhaps in a type of separated or bucket conveyor with an encoder so that you have an index value for each bucket, move on to a diverter system that is linked to the index encoder/counter, divert to a container based on color/bad read/empty index. Like I said there are so many ways but if you design it in phases then some of the ideas in this thread might become useful.
I don't see any need for a Raspberry Pi. All you have is colour detecting, decision making and steering some mechanics. All this done seemingly at the same time. No big data, no AI. An Arduino can do that.
let's say for a red cap it takes 2 seconds for it to reach the sorting arm and during that time another color pass in front of the color sensor, but since the code sequence for redcap is still in process Arduino wont be able to read the other color, right?
or is there a way to make the color sensor keep detecting colors while Arduino drive a servomotor? A code function that doesn't involve "if else" and "delay" function maybe?
Add an encoder to the conveyor so you can track its movement. Every X units of conveyor travel equals Y encoder pulses. When the color sensor registers a color drop a code for that color into a shift register stage relating to the sensor position. When no color is sensed drop in a '0'. This way you have an analog of where a cap is on the conveyor and you know its color. As the cap moves downstream continue tracking it and actuate your diverter when a certain color appears in a certain shift register stage.
Yes. Your code commands the servo with one single function, like myservo.write(queue[n]);. Once your code has performed that line, the servo starts working on its own, while your program does other things. The task of your program is to keep track of time.
1 is a laser beam detecting caps.
2 is the colour sensor.
3 is the servo twisting a tube to make the cap fall into the right jar.
The laser beam times everything. When the light breaks, it creates a new task with a time stamp. As long as the beam is broken, no new tasks are created.
The colour sensor checks the time stamp of the next task, or does nothing if there are no tasks. If the right time has passed, it reads the colour and records it for the task, otherwise it does nothing.
The servo checks the time stamp of the next task, or does nothing if there are no tasks. If the right time has passed, it rotates to the right angle, otherwise it does nothing.
The tasks have to be placed in a queue, an array of some kind. Your loop() would look like:
The program waits at no point. The loop might perform thousands times per seconds, it doesn't matter. Each function performs its own task. If its time to do something, it does it. If not, it does nothing and lets the program continue.