Pull to refresh

Что будет если смешать орехи, Arduino, OpenCV и Delphi. Часть 1

Reading time 4 min
Views 19K
Привет, хабровчанин.

Писатель из меня не очень, на это неоднократно указывали мне учителя в школе после прочтения моих сочинений. Не то что что-бы суть не была изложена, меня упрекали в сухости и лаконичности повествования. Тогда мне это казалось придирками, ведь лаконичность — это замечательно. Но не для писателя. В этот раз я попытаюсь исправится, ведь с того времени прочитаны тонны сайфая. Такова преамбула, и не исключено, что осиливший этот текст до конца всплакнет кровавой слезой, но я предупредил.

Удосужилось мне счастливо жить в небольшом городке в центральной Украине. Причины сего мне не известны, но каждую осень колхозный рынок превращается в биржу по торговле грецким орехом, его везут со всей округи. Все покупают и продают как одетый так и раздетый орех. Ажиотаж затрагивает как профессиональных перекупщиков, так и пенсионеров, мне при этом почему-то вспоминаются голландские тюльпаны. Но история началась летом.

С моим кумом мы владеем небольшим компьютерным магазинчиком, где он продает, а я занимаюсь мелким ремонтом и программированием. В очередной раз приехав с недельного отдыха с палатками на берегу реки, загоревший и нарыбачившийся вдоволь я сидел и что-то паял в своем кабинете, который я лаского зову «склеп» по причине обилия мертвого железа и постоянной температуры окружающей среды.

— К тебе пришли.

Я вышел из склепа и познакомился с парнем немного старше меня по имени Андрей. На ладони у него были половинки ядер грецкого ореха, одно темно-коричневое, почти черное, другое — светлое, практически бежевое. Андрей предложил работу, нужно было программно отделять первые от вторых. Это была первая ошибка. Нет, не подумайте плохо, ошибка не в том, что он связался со мной, а в том что принес мне настолько разные примеры. Мне была дана полная свобода в плане платформ и реализаций. Хоть и было предложено использовать камеры, я их отбросил, ввиду, как мне тогда показалось, сложности реализации и ресурсоемкости такого подхода. В качестве сенсора был выбран датчик tcs3200 — преобразователь цвет->частота, такие часто используют в DIY проектах по сортировке чего-нибудь цветного. По даташиту датчик имел хорошие характеристики: имел по 16 фотодиодов каждого цвета(R/G/B) плюс отдельно 16 фотодиодов для белого цвета. Глубина чувствительности каждого канала была заметно выше 8 бит на канал, которые предлагает бытовая вебкамера. Первая версия устройства представляла собой картонную трубу от пищевой фольги с вырезанным окошком для датчика и подсветки. Данные с максимально-возможной скоростью передавались в виндовое приложение. Получалось около 600 замеров в секунду.

image image
Фото не мои, взяты с сети, фотографий первого прототипа, увы, не осталось. Сам же прототип был порван детьми, когда они (и прототип и дети) были оставлены без присмотра.


На скриншоте приложения графики на черном фоне пришлось нарисовать в фотошопе по памяти. Далее все иллюстрации будут реальными.

Орехи скользили поштучно по трубе, наклоненной на 45 градусов, и если данные с датчика отличались от фона (предварительно калиброванного) — фиксировался орех и его средневзвешенный цвет. По этому значению и сортировались орехи, признаю, довольно примитивный алгоритм, тем не менее он отменно работал.
Скетч для 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);

  Serial.begin(9600);
   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) {
    getColor();
    Serial.write(lowByte(red));
    Serial.write(highByte(red));
    
    Serial.write(lowByte(green));
    Serial.write(highByte(green));
    
    Serial.write(lowByte(blue));
    Serial.write(highByte(blue));
    
    Serial.write(lowByte(white));
    Serial.write(highByte(white));
   
    delayMicroseconds(25);
  }
  if (comm == 66) {
    digitalWrite(ejector, HIGH);
    delayMicroseconds(10000);
    digitalWrite(ejector, LOW);
  }
  
  if (comm == 67) {
    Serial.end();
    Serial.begin(9600);
     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);

}


imageimage
Фотографии, где видно разницу между первыми и вторыми орехами.

С теми сэмплами что дал мне Андрей работало все прекрасно и отделяло темные от светлых орехов с точностью в 95%. Какой же был эпик фэйл когда в следующий раз были принесены орехи с менее контрастными различиями. Поделка отказывалась различать орехи, ведь их средневзвешенный цвет был практически одинаков. Была предпринята попытка анализировать орехи по графикам время/насыщенность цвета, но это не дало желаемых результатов, датчик на таких скоростях прилично шумел. В результате чего было принято решение переходить на камеры.

Но об этом во второй, заключительной части, будет интересней, обещаю.



PS: Добавил скетч

Обещанная вторая часть.
Tags:
Hubs:
+10
Comments 9
Comments Comments 9

Articles