Да, он работает. Этот странный датчик, по цене пяти народных. Работает как-то так: Приобрел я его по случаю в количестве двух штук, когда делал самый первый проект на Ардуино. Мучился с ним безумно долго, как-то запустил... А второй оказался нерабочим. Или я его "убил" в процессе мучений. В общем, после осознания смерти, изучение интернета показало, что есть много других измерителей расстояний. Валялся бы одинокий URM себе еще, но работа над второй версией подсветки лестницы предъявила к ультрасонику повышенное требование - скорость. И я вспомнил, что 990 рублей, потраченные на этот датчик, хоть как-то должны вернуться - у датчика есть некоторые особенности (хотя не факт, что они стоят именно столько). Еще день мучений, и теперь я могу пошагово рассказать вам как включить автоматический режим работы этого датчика, когда он: - сам измеряет расстояние; - сам сравнивает с референсным; - сам дрыгает ножку, если расстояние меньше запланированного; - сам выдает PWM сигнал, который позволяет без напряга узнать расстояние.Сначала скетч. А потом пояснения к нему, которых будет больше скетча. Код (C): // # Connection: // # Pin 1 VCC (URM V3.2) -> VCC (Arduino) // # Pin 2 GND (URM V3.2) -> GND (Arduino) // # Pin 6 COMP/TRIG (URM V3.2) -> Pin 2 (Arduino) // # Pin 4 PWM (URM V3.2) -> Pin 7 (Arduino) int cmmd1[]={ 0x44,0x00,0x05,0x49};//low byte stored in the sensor for the distance threshold. int cmmd2[]={ 0x44,0x01,0x00,0x45};//high byte, write 0x0010 into address 0x01 and 0x00,so the threshold is set to 16cm int cmmd3[]={ 0x44,0x02,0xaa,0xf0};// Autonomous mode. write 0xaa into address 0x02 //int cmmd3[]={ // 0x44,0x02,0xbb,0x01}; // PWM mode. write 0xbb into address 0x02 int i; unsigned int pwmUrm; void setup(){ Serial.begin(9600); // Sets the baud rate to 9600 A_Mode_Setup(); //PWM mode setup function pinMode(13, OUTPUT); } void loop() { pwmUrm = pulseIn(7, LOW); Serial.println(pwmUrm/50); // Узнаем через порт расстояние; //delay(1000); byte s = digitalRead(2); Serial.println(s); // Наблюдаем за срабатыванием на 5 см; digitalWrite(13,!s); } void A_Mode_Setup(){ //write the data into the URM37 EEPROM for (i=0;i<4;i++) Serial.write(cmmd3[i]); delay(200); for (i=0;i<4;i++) Serial.write(cmmd1[i]); delay(200); for (i=0;i<4;i++) Serial.write(cmmd2[i]); delay(200); }
Итак, если вы соедините все как указано в скетче и запустите его - ничего полезного не случится. Хотя скетч абсолютно рабочий. В чем прикол? Прикол в том, что включать/выключать всю конструкцию надо по-особенному. Итак: присоединяем проводочки так, как указано в скетче, грузим его в Ардуино и не обращаем внимание на то, что ничего не получается. Главное - прошиться; все отключаем от электронов, то есть обесточиваем; находим еще два проводочка, и соединяем их так: 9 ножка URM - 0 ножка Ардуино, 8 ножка URM - 1 ножка Ардуино. Догадались? Да, это будет uart соединение; откладываем в сторонку кабель USB, находим 5вольт и запитываем Ардуинку именно таким образом - только внешним источником питания; чуть ждем когда оно замигает, заработает; находим кнопочку сброса на Ардуинке и нажимаем с любовью (это очень важно, иначе с URMом не справиться!); отпускаем кнопочку и еще немного ждем; отсоединяем Ардуино от питания; отсоединяем проводки от 0 и 1 входов Ардуинки; включаем питание вновь... И вот он, момент истины. Только если Вы любите и Ардуино, и датчик URM (в особенности), то при поднесении ладошки к нему на пять сантиметров загорится лампочка диода на 13 ножке. ... а почему именно на 5 см. и как это расстояние изменить, и как читается вообще расстояние - объясню завтра. Хотя из кода кое-что может быть понятно...
Теперь разберемся с тем, что же мы натворили. Но перед этим узнаем, что URM37 работает в трех режимах по выбору: по UART после получения запроса отвечает измеренным расстоянием; после пинка в ногу 6 отвечает о расстоянии PWM на 4 ноге ; сам измерят дистанцию раз в 25 мс., сам щелкает 6 ногой о том, ближе или дальше чем задумано, а на 4 ноге постоянно держит PWM сигнал для чтения дистанции. Вот этот, третий режим мы и прихватили сейчас. Как мы это сделали? Все переключения режимов и объяснения строптивому URM37 правил жизни осуществляются только по UART. Это необходимо запомнить. Причем режим 1 включен постоянно - ультрасоник всегда готов пообщаться по протоколу. Второй и третий режимы включаются путем подачи UART команд, сотстоящих из 4 байтов. Для включения третьего режима надо подать три команды. Первая и вторая (младший байт расстояния, старший байт расстояния) запоминает в памяти ультрасоника контролируемое расстояние, а третья, собственно, и включает режим. Рассмотрим первую команду - младший байт: { 0x44,0x00,0x05,0x54} 0x44 - запись во внутреннюю память, 0x00 - адрес памяти, 0х05 - наши 5 см, 0x54 - (обязательно!) сумма первых трех цифр. Считать ее очень просто. Находите на вашем компе стандартную программу Калькулятор, включаете Вид -> Программист... а дальше сами разберетесь. Теперь понятно, что команда {0x44,0x01,0x00,0x45} значит записать во внутреннюю память по адресу 0х01 число 0, а в сумме 0x44+0x01+0x00= 0x45. Третья команда тоже разъясняется. {0x44,0x02,0xaa,0xf0} Записать в ячейку 03 число 0хаа (что и значит войти в третий режим), а сумма этого действа - 0xf0. Ясно и то, для чего исполняются все манипуляции со включением-выключением. Поскольку UART задействуется для связи и с USB и с URM37, вместе они не работают. Значит всегда последовательность будет такой. Программируем Ардуино, отсоединяем от USB, но присоединяем к URM37, включаем, происходит запись по UART, после чего ультрасоник еще и требует перезагрузки - отключения и включения питания.
Во втором и третьем режиме на 4 ноге ультрасоника по команде (2 режим) или постоянно (третий режим) присутствует PWM сигнал, который мы ловим командой pulseIn((номер присоединенной ноги Ардуино), LOW);. Его каждые 50 мкс соответствуют 1 см. значит поделив результат на 50 мы получаем расстояние в сантиметрах. Проще не куда! Вот и этот код: Код (Text): pwmUrm = pulseIn(7, LOW); Serial.println(pwmUrm/50); А код Код (Text): byte s = digitalRead(2); Serial.println(s); digitalWrite(13,!s); читает 6 ногу ультрасоника, печатает значение (0 или 1) в порт и зажигает лампочку, причем с инверсией. Ультрасоник держит на 6 ноге единицу, если расстояние больше указанного, и 0 - если меньше.
Наконец, пора записать другое расстояние в память. Давайте, предположим, 330 см. Алгоритм: открываем Калькулятор и записываем в него 330 в десятичном виде; переключаем в шестнадцатеричный и получаем 14А; врубаемся, что младший байт расстояния - 0х4а, а старший 0х01; составляем первую команду: 0x44,0x00,0x4а,0x8e. Понятно, что 0x8e = 0x44+0x00+0x4а? Кстати, калькулятор то не закрываем - это я на нем и посчитал. вторая команда: 0x44,0x01,0x00,0х45. третья: 0x44,0x02,0xaa,0xf0. Ее и считать не надо - просто копируем. Повторяем все описанные выше волшебные пассы, и наш умный URM размера 37 начинает контролировать дистанцию 330 см.
А теперь превратим URM37 в обычный датчик. Для этого вместо трех команд запишем в память всего одну: {0x44,0x02,0xbb,0x01}; Разбирать ее нет смысла - проще записать. А для дотошных - запись в память по адресу 2 числа 0xbb. Сумма 0x44 + 0x02 + 0xbb равна 0х0101, но в команду подается младший байт, а именно - 0х01. Это, в целом, все. Добавлю, что пятой ногой ультрасоник может командовать сервой. Как это делается, желающие могут разобраться самостоятельно, уверен, предоставленной выше информации хватит для укрощения девайса. И напоследок две главные ссылки, где есть больше объяснений и материалов: раз и два.
Достал, улыбнулся... . Два года прошло. Стряхнул пыль. Загрузил скрипт: Код (Javascript): var cmd=[]; var count = 0; var distance = 0; C3.set(); // light on SPI1.setup({sck:A5, miso:A6, mosi:A7, baud: 1000000}); Serial6.setup(9600); Serial6.on('data', function (data) { // console.log(data.charCodeAt(0)); cmd[count] =data.charCodeAt(0); count +=1; if (count === 4){ // console.log(cmd); getDistanse(cmd); cmd = []; count = 0; } }); var cmmd3=[0x44,0x02,0xaa,0xf0];// Autonomous mode var cmmd4=[0x44, 0x02, 0xbb, 0x01]; // passive PWM mode Serial6.write(cmmd4); var cmmd5=[0x11,0x00,0x00,0x11]; // temperature var cmmd6=[0x22,0x00,0x00,0x22]; // distance function getDistanse(rawdata) { if(rawdata[0] !== 255) { var newdistance = (rawdata[1]*255+rawdata[2]); if (newdistance !== distance) { console.log("Distance is "+ newdistance +" cm."); //printLCD("123"); distance = newdistance; } return newdistance; } else{ console.log("Error to get distance!"); return rawdata[0]; } } Serial6.write(cmmd6); setInterval(function(){ Serial6.write(cmmd6); }, 1000); var g = require("ILI9341").connect(SPI1, B1, B0, C2, function() { g.setFontVector(45); g.setColor(0,0.5,1); var oldolddistance = 0; setInterval( function () { if (distance !== oldolddistance) { g.clear(); var r = Math.random(); var gr = Math.random(); var b = Math.random(); while ((r+gr+b) < 1) { r = Math.random(); gr = Math.random(); b = Math.random(); } g.setColor(r,gr,b); g.drawString(distance + " cm.",45,150); oldolddistance = distance; } },2000 ); });