What happens if you mix nuts, Arduino, OpenCV and Delphi. Part 1

    Hello, habrovchanin.

    The writer from me is not very, this was repeatedly pointed out to me by teachers at school after reading my essays. Not that the essence was not stated, I was reproached for the dryness and brevity of the narrative. Then it seemed to me nitpicking, because laconicism is wonderful. But not for the writer. This time I’ll try to get better, because from that time tons of saifai have been read. This is the preamble, and it is possible that one who has mastered this text will cry a bloody tear to the end, but I warned.

    I bothered to live happily in a small town in central Ukraine. I don’t know the reasons for this, but every autumn the collective farm market turns into a walnut exchange, it is taken from all over the district. Everyone buys and sells both dressed and stripped nuts. The excitement affects both professional resellers and retirees, for some reason I remember the Dutch tulips. But the story began in the summer.

    With my godfather, we own a small computer store where he sells, and I do minor repairs and programming. Once again, having arrived from a week's rest with tents on the river bank, sunbathing and fishing enough, I sat and soldered something in my office, which I affectionately call “crypt” due to the abundance of dead iron and a constant ambient temperature.

    - They came to you.

    I got out of the crypt and met a guy a little older than me named Andrei. On his palm he had halves of walnut kernels, one dark brown, almost black, the other light, almost beige. Andrew offered a job, it was necessary to programmatically separate the first from the second. This was the first mistake. No, don’t think badly, the mistake is not that he contacted me, but that he brought me so different examples. I was given complete freedom in terms of platforms and implementations. Although it was proposed to use cameras, I rejected them, in view of, as it seemed to me then, the complexity of the implementation and resource consumption of such an approach. The tcs3200 sensor was selected as the sensor- color-> frequency converter, these are often used in DIY projects for sorting something colored. According to the datasheet, the sensor had good characteristics: it had 16 photodiodes of each color (R / G / B) plus 16 photodiodes separately for white. The sensitivity depth of each channel was noticeably higher than 8 bits per channel, which offers a home webcam. The first version of the device was a cardboard tube from food foil with a cut out window for the sensor and backlight. Data was transferred to the Windows application with the highest possible speed. It turned out about 600 measurements per second.

    Photos are not mine, taken from the network, photos of the first prototype, alas, no more. The prototype itself was torn by children when they (both the prototype and the children) were left unattended.

    In the screenshot of the application, graphics on a black background had to be drawn in Photoshop from memory. Further, all illustrations will be real.

    Nuts slid piece by piece along the pipe, tilted by 45 degrees, and if the data from the sensor differed from the background (pre-calibrated), the nut and its weighted average color were fixed. By this value nuts were sorted, I admit, a rather primitive algorithm, nevertheless it worked perfectly.
    Sketch for Leonardo
    const int s0 = 12; // sensor pins
    const int s1 = 13;
    const int s2 = 11;
    const int s3 = 10;
    const int out = 9; // TCS230 output
    const int ejector = 7;
    int red = 0;
    int green = 0;
    int blue = 0;
    int white = 0;
    int comm = 0;
    void setup() {
      pinMode(s0, OUTPUT);
      pinMode(s1, OUTPUT);
      pinMode(s2, OUTPUT);
      pinMode(s3, OUTPUT);
      pinMode(out, INPUT);
      pinMode(ejector, OUTPUT);
       while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
      digitalWrite(s0, HIGH);
      digitalWrite(s1, HIGH);  //l
    void loop() {
      if (Serial.available() > 0) {
        comm = Serial.read();
      if (comm == 65) {
      if (comm == 66) {
        digitalWrite(ejector, HIGH);
        digitalWrite(ejector, LOW);
      if (comm == 67) {
         while (!Serial) {
          ; // wait for serial port to connect. Needed for Leonardo only
    void getColor() {
      digitalWrite(s2, LOW);
      digitalWrite(s3, LOW);
      red = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);
      digitalWrite(s3, HIGH);
      blue = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);
      digitalWrite(s2, HIGH);
      green = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);
      digitalWrite(s3, LOW);
      white = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);

    Photos showing the difference between the first and second nuts.

    With those samples that Andrey gave me, everything worked perfectly and separated dark from light nuts with an accuracy of 95%. What was the epic file the next time nuts with less contrasting differences were brought. Craft refused to distinguish nuts, because their weighted average color was almost the same. An attempt was made to analyze the nuts on the graphs of time / color saturation, but this did not give the desired results, the sensor at these speeds decently made noise. As a result, it was decided to switch to cameras.

    But about this in the second, final part, it will be more interesting, I promise.

    PS: Added a sketch The

    promised second part.

    Also popular now: