Прошу форумчан пнуть в нужном направлении. Бьюсь уже несколько дней) Связка Ардуино Уно и AI камера Huskylens плюс 2 сервы. Стоит задача поиска и слежения за лицом. В части слежения за лицом реализовать удалось. В части поиска лица (поворот сервы в одну сторону и в другую) не совсем. Есть код: Код (C++): #include <Servo.h> // подключаем библиотеку для работы с сервоприводом #include "HUSKYLENS.h" #include "SoftwareSerial.h" Servo servo1; Servo servo2; HUSKYLENS huskylens; SoftwareSerial mySerial(A4, A5); // RX, TX //HUSKYLENS green line >> Pin 10; blue line >> Pin 11 void printResult(HUSKYLENSResult result); int angle1 = 80; int angle2 = 95; void setup() { Serial.begin(115200); servo1.attach(5); servo2.attach(3); servo1.write(angle1); servo2.write(angle2); Wire.begin(); while (!huskylens.begin(Wire)) { Serial.println(F("Begin failed!")); Serial.println(F("1.Please recheck the \"Protocol Type\" in HUSKYLENS (General Settings>>Protocol Type>>I2C)")); Serial.println(F("2.Please recheck the connection.")); delay(100); } huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION); } void loop() { if (!huskylens.request()) Serial.println(F("Fail to request data from HUSKYLENS, recheck the connection!")); else if(!huskylens.isLearned()) Serial.println(F("Nothing learned, press learn button on HUSKYLENS to learn one!")); else if(!huskylens.available()) Serial.println(F("No block or arrow appears on the screen!")); // Если лицо не обнаружено, в мониторе выводится это сообщение else { HUSKYLENSResult result = huskylens.read(); printResult(result); // Код слежения за лицом (работает) if (result.xCenter>200) { Serial.println(result.xCenter); angle1 -= 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay (10); } else if (result.xCenter>10 && result.xCenter <120 ) { angle1 += 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay (10); } if (result.yCenter>150) { angle2 -=1.5; servo2.write(abs((constrain(angle2, 75, 140)))); delay (30); } else if (result.yCenter>10 && result.yCenter <100 ) { angle2 +=1.5; servo2.write(abs((constrain(angle2, 75, 140)))); delay (30); } } } void printResult(HUSKYLENSResult result){ if (result.command == COMMAND_RETURN_BLOCK){ Serial.println(String()+F("Block:xCenter=")+result.xCenter+F(",yCenter=")+result.yCenter+F(",width=")+result.width+F(",height=")+result.height+F(",ID=")+result.ID); } else if (result.command == COMMAND_RETURN_ARROW){ Serial.println(String()+F("Arrow:xOrigin=")+result.xOrigin+F(",yOrigin=")+result.yOrigin+F(",xTarget=")+result.xTarget+F(",yTarget=")+result.yTarget+F(",ID=")+result.ID); } else{ Serial.println("Object unknown!"); } } Как я понял, когда лицо обнаружено, срабатывает условие из 46 строчки, как только лицо теряется, срабатывает из 44 строки. Когда лицо не обнаружено, хочу сделать, чтобы серва крутила камеру в поисках лица. Но как только я вставляю код поворота сервы в условие 44 строки, даже при обнаружении лица, условие из 46 строки уже не срабатывает. Серва так и продолжает крутить камеру от 0 до 180 градусов. Что я делаю не так? И еще вопрос. В loop в 42, 43 и 44 строках указаны восклицательные знаки. Насколько я понимаю. знак ! - отрицание. К чему он в этих переменных? Код (C++): if (!huskylens.request()) Serial.println(F("Fail to request data from HUSKYLENS, recheck the connection!")); else if(!huskylens.isLearned()) Serial.println(F("Nothing learned, press learn button on HUSKYLENS to learn one!")); else if(!huskylens.available()) Буду благодарен за комментарии, подсказки, замечания.
Функции request(), isLearned() и available() возвращают двоичное (bool) значение. Вот и получается буквально: if(!huskylens.isLearned()) - если не изучил, if(!huskylens.available()) - если не доступен.
Смотря как вы это реализовали. Например, можно поворачивать камеру на +10 градусов и выходить на проверку. Потребуется задержка (delay), чтобы камера успела повернуться, а потом уже начиналось слежение за лицом.
так вроде сперва составляют алгоритм работы программы, а уже потом её пишут? Здесь же полное непонимание того, как МК выполняет программу.
Спасибо, получается, что после if(!huskylens.available()) следующий else, в котором код слежения сервы за лмцом, означает буквально - если доступен huskylens.available(). По логике в условие если НЕ доступен if(!huskylens.available()) нужно вставить код вращения сервы влево-вправо, и как только камера зафиксирует лицо, huskylens.available() должен стать доступен. Но у меня этого не происходит, несмотря на то,что камера лицо фиксирует
Пробовал так Код (C++): void loop() { if (!huskylens.request()) Serial.println(F("Fail to request data from HUSKYLENS, recheck the connection!")); else if(!huskylens.isLearned()) Serial.println(F("Nothing learned, press learn button on HUSKYLENS to learn one!")); else if(!huskylens.available()) {Serial.println(F("No block or arrow appears on the screen!")); // Если лицо не обнаружено, в мониторе выводится это сообщение // Код сканирования лица для сервы for (angle1; angle1 <= 180; angle1 += 1) { servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } for (angle1; angle1 >= 0; angle1 -= 1) { servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } } } else { HUSKYLENSResult result = huskylens.read(); printResult(result); // Код слежения за лицом (работает) if (result.xCenter>200) { Serial.println(result.xCenter); angle1 -= 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay (10); } else if (result.xCenter>10 && result.xCenter <120 ) { angle1 += 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay (10); } if (result.yCenter>150) { angle2 -=1.5; servo2.write(abs((constrain(angle2, 75, 140)))); delay (30); } else if (result.yCenter>10 && result.yCenter <100 ) { angle2 +=1.5; servo2.write(abs((constrain(angle2, 75, 140)))); delay (30); } } } но условие, когда huskylens.available доступен не срабатывает. Если код сервы сканирования удалить. то срабатывает мгновенно
Код (C++): // Код сканирования лица для сервы for (angle1; angle1 <= 180; angle1 += 1) { servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } for (angle1; angle1 >= 0; angle1 -= 1) { servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } } } Я так понял, цикл for влияет на выполнение условия. Потому что без него сообщение в монитор No block or arrow appears on the screen сыпится ежесекундно, а с кодом сервы разового после каждого прохода сервы. Пробовал while с условием !huskylens.available(), аналогично. P.S убрал вообще for, заработало) Сейчас так Код (C++): else if(!huskylens.available()) {Serial.println(F("No block or arrow appears on the screen!")); // Если лицо не обнаружено, в мониторе выводится это сообщение angle1 += 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } Только не понятно. как без цикла заставить серву вращаться в обратную сторону/ P.S.2 Сам спросил, сам ответил. Еще одним условием Код (C++): if (angle1 <= 180) { angle1 += 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } else if (angle1 >= 0) { angle1 += 1; servo1.write(abs((constrain(angle1, 10, 170)))); delay(50); } Я так понимаю, все ломалось из-за использования for и while. Но теперь серва делает проход однократно, вместо того, чтобы крутится в другую сторону до момента поиска лица
А если так: Код (C++): // Код сканирования лица для сервы int step = 1; // to right if (!reverse && angle1 <= 180) angle1 += step; else reverse = true; // to left if (reverse && angle1 >= 0) angle1 -= step; else reverse = false; // write servo1.write(abs((constrain(angle1, 10, 170)))); delay(step * 50); Только в начале кода (перед setup) нужно добавить: Код (C++): bool reverse = false;
Благодаря помощи форумчан продвинулся чуть дальше. Решил не делать отдельную тему. Собственно сейчас это представляет из себя связку UNO с камерой Huskylens, 2 сервами и модулем DFPlayer. Алгоритм работы такой: при включении камера за счет серв сканирует несколько раз пространство вокруг, если видит кого-то из знакомых, то переходит в режим слежения на лицом и DFPlayer в зависимости от ID лица воспроизводит одно из приветствий. Проблема в том, что если добавлять код с условиями проверки ID лиц, то сервы в режиме слежения за лицом работают значительно медленнее. Думал, что не справляется Уно, попробовал на есп32, но результат тот же. Скорее всего виной мой кривой код) Если пнете в нужном направлении, буду благодарен. Сам код Код (C++): #include <Servo.h> // подключаем библиотеку для работы с сервоприводом #include "HUSKYLENS.h" // подключаем библиотеку для работы HUSKYLENS #include "SoftwareSerial.h" #include "DFPlayer_Mini_Mp3.h" // подключаем библиотеку для работы DFPlayer Servo servo1; Servo servo2; HUSKYLENS huskylens; SoftwareSerial mySerial(A4, A5); // RX, TX //HUSKYLENS green line >> Pin 10; blue line >> Pin 11 void printResult(HUSKYLENSResult result); int angle1 = 90; // положение сервы при включении int angle2 = 105; // положение сервы при включении bool reverse2 = false; bool hallo = true; bool hallo2 = true; bool hallo3 = true; bool trackingSonya = false; bool trackingSonya2 = false; int stopscan = 0; void setup() { Serial.begin(115000); servo1.attach(5); servo2.attach(2); servo1.write(angle1); servo2.write(angle2); mp3_set_serial (Serial); mp3_set_volume (30); delay (3000); Wire.begin(); while (!huskylens.begin(Wire)) { Serial.println(F("Begin failed!")); Serial.println(F("1.Please recheck the \"Protocol Type\" in HUSKYLENS (General Settings>>Protocol Type>>I2C)")); Serial.println(F("2.Please recheck the connection.")); delay(100); } } void loop() { if (!huskylens.request()) Serial.println(F("Fail to request data from HUSKYLENS, recheck the connection!")); else if(!huskylens.isLearned()) Serial.println(F("Nothing learned, press learn button on HUSKYLENS to learn one!")); else if (!huskylens.available()) {Serial.println ("Scan"); // Если лицо не обнаружено, в мониторе выводится это сообщение // Код поиска лиц - нижний проход, вверх, вкерхний проход, вниз. По достижении stopscan 100 останиваливается. если ничего не нашел if (stopscan < 100) { Serial.println (String("stopscan") + String(stopscan)); int step = 2; // to right if (!reverse2 && angle1 <= 180) {angle1 += step; Serial.println ("right"); } else if(angle1 > 180 && angle2 < 120) { angle2 += step; Serial.println ("top"); } else if (angle2 >= 120 && angle1 > 10) { angle1 -= step; reverse2 = true; Serial.println ("left"); } else if (reverse2 && angle1 <= 10 && angle2 > 85){ angle2 -= step; Serial.println ("down"); stopscan +=1; } else reverse2 = false ; // write servo1.write(abs((constrain(angle1, 10, 170)))); Serial.println (angle1); servo2.write(abs((constrain(angle2, 85, 130)))); Serial.println (angle2); delay(step * 40); } } else { HUSKYLENSResult result = huskylens.read(); printResult(result); // Код слежения за лицом if (result.xCenter>200) { //Serial.println (result.ID); //Serial.println (String("x") + (result.xCenter) + ("servox") + (angle1)); //Serial.println (String("y") + (result.yCenter) + ("servoy") + (angle2)); angle1 -= 2; servo1.write(abs((constrain(angle1, 10, 170)))); delay (30); } else if (result.xCenter>10 && result.xCenter <=120 ) { //Serial.println (result.ID); //Serial.println (String("x") + (result.xCenter) + ("servox") + (angle1)); //Serial.println (String("y") + (result.yCenter) + ("servoy") + (angle2)); angle1 += 2; servo1.write(abs((constrain(angle1, 10, 170)))); delay (30); } if (result.yCenter>150) { //Serial.println (result.ID); //Serial.println (String("x") + (result.xCenter) + ("servox") + (angle1)); //Serial.println (String("y") + (result.yCenter) + ("servoy") + (angle2)); angle2 -=1; servo2.write(abs((constrain(angle2, 75, 130)))); delay (30); } else if (result.yCenter>10 && result.yCenter <= 90 ) { //Serial.println (result.ID); //Serial.println (String("x") + (result.xCenter) + ("servox") + (angle1)); //Serial.println (String("y") + (result.yCenter) + ("servoy") + (angle2)); angle2 +=1; servo2.write(abs((constrain(angle2, 75, 130)))); delay (30); } // Однократное привествие лица ID2 if (hallo && huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION) && result.ID == 2) { mp3_play (1); delay (2000); hallo = false; } // Однократное привествие лица ID1 if (hallo2 && huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION) && result.ID ==1) { mp3_play (2); hallo2 = false; trackingSonya = true; } // Второе привествие для ID1 if (trackingSonya && !trackingSonya2 && result.ID ==1) { mp3_play (3); trackingSonya2 = true; } } } void printResult(HUSKYLENSResult result){ if (result.command == COMMAND_RETURN_BLOCK){ //Serial.println(String()+F("Block:xCenter=")+result.xCenter+F(",yCenter=")+result.yCenter+F(",width=")+result.width+F(",height=")+result.height+F(",ID=")+result.ID); } else if (result.command == COMMAND_RETURN_ARROW){ Serial.println(String()+F("Arrow:xOrigin=")+result.xOrigin+F(",yOrigin=")+result.yOrigin+F(",xTarget=")+result.xTarget+F(",yTarget=")+result.yTarget+F(",ID=")+result.ID); } else{ Serial.println("Object unknown!"); } }
Наверно, проверка ID занимает много времени. Тут никак не ускорить. Можно попробовать увеличить угол (шаг) поворота камеры, градусов 20-30. Но это не точно.