Вывод сигнала по 2ум ногам ардуино в виде частоты.
- Войдите на сайт для отправки комментариев
Втр, 08/08/2017 - 09:40
Привет. Стоит задача. нужно выводить 2 изменяющихся ссигнала с 2х ножек ардуино.
Как это выглядит:
1. с датчиков поступают сигналы на ардуино
2. ардуино превращает сигналы в частоту
3. выводит эту частоту на ноги ардуины.
4. честотомер будет мерить это частоту и понимать что есть что.
Я пытался собрать на tone, но не выходит. Пполучается такая картинка на осцилографе
____||||||||||_____|||||||||______|||||||||_____ одна нога ардуино
|||||||_____|||||||||______||||||||||_____||||||||| другиая нога
этот рисунок означает что пока импульсы идут по одной ноге, по друго й мочит и на оборот.
как можно сделать чтобы работало паралельно...
вот мой код
// программа инклинометрии // ноги датчика ардуино // VCC 3.3V // GND GND // SCL A5 // SDA A4 // ноги дисплея ардуино // VSS GND // VDD 5V // V0 через резистор на GND // RS D6 // RW GND // E D7 // D4 D5 // D5 D4 // D6 D3 // D7 D2 // A 5V // K GND //===================================================================== // подключение библиотек #include <Wire.h> // библиотека по которой общается датчик с ардуиной #include <LSM303.h> // библиотека самого датчика #include <LiquidCrystal.h> // а это библиотека для вывода значений на дисплейчик 1602A //===================================================================== LSM303 compass; char report[80]; //===================================================================== // переменные, с которыми будем работать float ax; // переменная хранящие данные оси X акселерометра float ay; // переменная хранящие данные оси Y акселерометра float az; // переменная хранящие данные оси Z акселерометра float m; // переменная хранящие данные азимута (сторона, куда повернут корпус датчика) float b1; // переменная хранящие данные угла наклона от 0 до 180 градусов. погрешность 0.05 градуса float b2; // переменная хранящая данные угла поворота наклона относительно оси X акселерометра. float b3; // переменная хранящая сумму азимута (сторона, куда повернут корпус прибора) и угла поворота наклона относительно оси X акселерометра. float b4; // переменная хранящая данные азимута наклона int chu, cha; //==================================================================== //==================================================================== //ноги дисплея const int rs = 6, en = 7, d4 = 5, d5 = 4, d6 = 3, d7 = 2; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //==================================================================== void setup() { pinMode(11, OUTPUT); pinMode(12, OUTPUT); Serial.begin(9600); Wire.begin(); lcd.begin(16, 2); lcd.print("inklinometr"); delay(2000); compass.init(); compass.enableDefault(); compass.m_min = (LSM303::vector<int16_t>){-32767, -32767, -32767}; // данные калибровки осей X Y Z compass.m_max = (LSM303::vector<int16_t>){+32767, +32767, +32767}; // данные калибровки осей X Y Z } void loop() { compass.read(); float heading = compass.heading(); snprintf(report, sizeof(report), "A: %6d %6d %6d M: %6d %6d %6d", compass.a.x, compass.a.y, compass.a.z, compass.m.x, compass.m.y, compass.m.z); //================================================================= //присваиваем переменным значения акселерометра float ax = compass.a.x; float ay = compass.a.y; float az = compass.a.z; float m = heading; // это собственно азимут который определяет на сколько градусов повернут корпус датчика //================================================================ //================================================================ // расчет в первом полушарие полушарии от 0 до 180 градусов //================================================================ if (ax > 0) //если значения оси X больше ноля { //==================================================== // расчет в первом квадранте от 0 до 90 градусов это если +X +Y //==================================================== if (ay > 0) //если хначения оси Y больше ноля { float b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы float b2 = (((atan((sqrt(sq(ax)))/sqrt(sq(ay)))))*180)/3.14; // расчет угла проекции вектора относительно оси Y. переменные возводятся в квадрат, а потом выводятся из него для выведения их модуля float b3 = b2 + m; // здесь идет сложения углов для определения в какую сторону наклонен датчик(азимут наклона) if (b3 > 359) // если сумма больше 360 градусов { float b4 = b3 - 359; // то просто от этой суммы вычитывается 360 и выводится на дисплей Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } else // а если нет, то выводится на дисплей как есть { float b4 = b3; Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } // выводится посчитанный зенитный угол Serial.print("ugol naklona = "); Serial.println(b1); lcd.setCursor(0, 2); lcd.print("zen="); lcd.print(b1); lcd.print(" "); chu = b1 * 100; noTone(12); tone(11,chu); } // конец расчета в первом квадранте от 0 до 90 градусов это если +X +Y //============================================================== //========================================================= // расчет во втором квадранте от 90 до 180 градусов это если +X -Y //========================================================= else //если значения оси Y меньше ноля { float b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы float b2 = ((((atan((sqrt(sq(ay)))/sqrt(sq(ax)))))*180)/3.14)+90; // расчет угла проекции вектора относительно оси X, т.к. мы уже во втором квадранте и прибавляем к полученным данным 90 float b3 = b2 + m; // здесь идет сложения углов, для определения в какую сторону наклонен датчик if (b3 > 359) // если сумма больше 360 градусов { float b4 = b3 - 359; // то просто от этой суммы вычитывается 360 и выводится на дисплей Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } else // а если нет, то выводится на дисплей как есть { float b4 = b3; Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } // выводится посчитанный зенитный угол Serial.print("ugol naklona = "); Serial.println(b1); lcd.setCursor(0, 2); lcd.print("zen="); lcd.print(b1); lcd.print(" "); chu = b1 * 100; noTone(12); tone(11,chu); } // конец расчета во втором квадранте от 90 до 180 градусов это если +X -Y //============================================================== } // конец расчета в первом полушарии от 0 до 180 градусов //================================================================ //================================================================ // расчет во втором полушарие полушарии от 180 до 360 градусов //================================================================ if (ax < 0) //если значения оси X меньше ноля { //======================================================= // расчет в третьем квадранте от 180 до 270 градусов это если -X -Y //======================================================= if (ay < 0) //если значения оси Y меньше ноля { float b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы float b2 = ((((atan((sqrt(sq(ax)))/sqrt(sq(ay)))))*180)/3.14)+180; // расчет угла проекции вектора относительно оси X, т.к. мы уже в третьем квадранте и прибавляем к полученным данным 180 float b3 = b2 + m; // здесь идет сложения углов, для определения в какую сторону наклонен датчик if (b3 > 359) // если сумма больше 360 градусов { float b4 = b3 - 359; // то просто от этой суммы вычитывается 360 и выводится на дисплей Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } else // а если нет, то выводится на дисплей как есть { float b4 = b3; Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } // выводится посчитанный зенитный угол Serial.print("ugol naklona = "); Serial.println(b1); lcd.setCursor(0, 2); lcd.print("zen="); lcd.print(b1); lcd.print(" "); chu = b1 * 100; noTone(12); tone(11,chu); } // конец расчета в третьем квадранте от 180 до 270 градусов это если -X -Y //============================================================== //========================================================= // расчет в четвёртом квадранте от 270 до 360 градусов это если -X +Y //========================================================= else //если значения оси Y больше ноля { float b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы float b2 = ((((atan((sqrt(sq(ay)))/sqrt(sq(ax)))))*180)/3.14)+270; // расчет угла проекции вектора относительно оси X, т.к. мы уже в третьем квадранте и прибавляем к полученным данным 270 float b3 = b2 + m; // здесь идет сложения углов, для определения в какую сторону наклонен датчик if (b3 > 359) // если сумма больше 360 градусов { float b4 = b3 - 359; // то просто от этой суммы вычитывается 360 и выводится на дисплей Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } else // а если нет, то выводится на дисплей как есть { float b4 = b3; Serial.print("azimut naklona4 = "); Serial.println(b4); lcd.setCursor(0, 0); lcd.print("azim="); lcd.print(b4); lcd.print(" "); cha = b4 * 100; noTone(11); tone(12,cha); } // выводится посчитанный зенитный угол Serial.print("ugol naklona = "); Serial.println(b1); lcd.setCursor(0, 2); lcd.print("zen="); lcd.print(b1); lcd.print(" "); chu = b1 * 100; noTone(12); tone(11,chu); } // конец расчета в четвертом квадранте от 270 до 360 градусов это если -X +Y //============================================================== } }
1. Прочитайте вот эту статью (не просто прочитайте. а скачайте калькулятор и побалуйстесь руками).
2 делайте одну частоту на 9-ом или 10-ом пине, точно, как написано в статье, а для второй напишите такой же ногодрыг для другого таймера.
А можно по-детальнее про пункт 4.
Как частотомер что то может понимать? Тем более ноги две, а частотомер один.
А можно по-детальнее про пункт 4.
Как частотомер что то может понимать? Тем более ноги две, а частотомер один.
в роли частотомера выступает выступает регистратор подключенный к компьютеру. регистратор имеет 3 канала регистрирующих инпульсы по положительному и отрицательному фронту относительно земли или питания. вообще я думаю это немного не относится к теме.
суть в том, что я сейчас пытаюсь собрать не регестрирующее устройство, а генерирующее. как я понимаю функция tone использует таймер, который после заполнения (которое изменяется вторым параметром в скобочке настройке) меняет состояние на ножке (которая указывается первым параметром в скобочках настройки).
я сейчас думаю обратиться к асемблеру, начать учить его. плохо то, что я не знаю как работают эти операторы, которые указаны в разделе "программирование" ардуино. некоторые слова я вообще не понимаю, я даже незнаю как искать это в гугле, я просто беру выделяю и вставляю то, что вижу. Я не хочу так делать, я написал сюда для того чтобы вы направили с какой стороны искать. Я благодарен ЕвгениюП за статью, что он предложил. Я прочту её, если есть еще что почитать, прошу, посылайте пожалуйста.
есть еще интересующий вопрос, хочу облегчить немного програму, неужели надо прописывать вывод данных на сериал и на лсиди в каждом цикле оператора иф
можно ли выводить данные на сериал и на лсиди после оператора иф, а не в каждом. если нет, то оставлю как есть, просто я вытаскивал их из циклов иф, но на дисплее ничего.... вот как то так.
можно ли выводить данные на сериал и на лсиди после оператора иф, а не в каждом
можно. Для этого переменные, которые Вы выводите(скажем b4) - должны быть описаны снаружи операторв иф, например глобально. В вашем же коде переменная b4 описана внутри каждого иф заново, поэтому когда вы выходите за пределы цикла, выводить нечего.
расскажите какой прескаллер использовать лучше ичто мне вбить в интернете для того чтобы понять что такое TCCR1A=0x40. откуда взято 0х40. я искал в даташите, в статьях о таймерах, но не могу понять. просто я хочу использовать еще 1 таймер, я буду читать еще, но подскажите что мне искать...
расскажите какой прескаллер использовать лучше
Там в статье есть калькулятор. Запустите, он скажет. Из тех, что он предложит, используйте любой.
ичто мне вбить в интернете для того чтобы понять что такое TCCR1A=0x40.
https://drive.google.com/open?id=0B9r7cRXQ4DU4YVdhcDhadUI0bFE Разделы 15-18 как раз про все таймеры.
что мне вбить в интернете для того чтобы понять что такое TCCR1A=0x40. откуда взято 0х40. я искал в даташите, в статьях о таймерах, но не могу понять. просто я хочу использовать еще 1 таймер, я буду читать еще, но подскажите что мне искать...
Родное сердце! Ты издеваешься или тупой?
В даташите с родного сайта. Глава про таймер1 со стр. 149, регистры со стр. 170.
------------------------------------------------------------------------------------
Ты какие, в жопу, "статью про таймеры" читал? И зачем ты их читал вместо документации на контроллер?
вот раскладываем Твои значения:
TCCR1A = 0x40 = 0b00010000 => COM1A = 0; COM1B = 01;
TCCR1B = 0x08 | 5 = 0b00001000 | 0b00000101 = 0b 00001101
=> COM1A = 0; COM1B = 01; WGM1= 0100; CS1 = 101; остальные переключатели все 0.
По таблицам смотрим:
WGM1=0100 - режис СТС, ТОП в регистре OCR1A; COM1B = 01 - переключение выхода при достижении топа.
CS1 = 101 - делитель 1024.
что-то непонятно написано в даташите? Или в школе тройка по аглицкому? Бабушку попроси перевести... или внучку.
А если ты станешь читать про таймеры в СТМ32, то там больше 10 конфигурационных регистров - совсем удавиться придется?
можно ли выводить данные на сериал и на лсиди после оператора иф, а не в каждом
можно. Для этого переменные, которые Вы выводите(скажем b4) - должны быть описаны снаружи операторв иф, например глобально. В вашем же коде переменная b4 описана внутри каждого иф заново, поэтому когда вы выходите за пределы цикла, выводить нечего.
большое спасибо! программа стала меньше на много. Теперь и ориентироваться в ней проще. Правда спасибо вам большое.
сейчас получилось сделать так, что бы программа выводила расчитанные данные в виде частоты на пин9 и пин 11(просто так вышло, не критично). импульсы в виде маендра нужной частоты, теперь хочу эти импульсы сделать кротковременными(ну типо одновибратора). почитаю еще, если есть идеи говорите буду читать и учиться.
зенитный угол выводится на пин 9 по тому методу, что описано в статье ЕвгенийП "Этюды для начинающих: blink и без delay, и без millis", а азимут(азимут наклона) выводится функцией tone на пин 11.