Вывод сигнала по 2ум ногам ардуино в виде частоты.

Anytcent
Offline
Зарегистрирован: 16.07.2016

Привет. Стоит задача. нужно выводить 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
    //==============================================================  
}
              
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1. Прочитайте вот эту статью (не просто прочитайте. а скачайте калькулятор и побалуйстесь руками).

2 делайте одну частоту на 9-ом или 10-ом пине, точно, как написано в статье, а для второй напишите такой же ногодрыг для другого таймера.

gena
Offline
Зарегистрирован: 04.11.2012

  А можно по-детальнее про пункт 4.

Как частотомер что то может понимать? Тем более ноги две, а частотомер один.

Anytcent
Offline
Зарегистрирован: 16.07.2016

gena пишет:

  А можно по-детальнее про пункт 4.

Как частотомер что то может понимать? Тем более ноги две, а частотомер один.

 

в роли частотомера выступает выступает регистратор подключенный к компьютеру. регистратор имеет 3 канала регистрирующих инпульсы по положительному и отрицательному фронту относительно земли или питания. вообще я думаю это немного не относится к теме.

суть в том, что я сейчас пытаюсь собрать не регестрирующее устройство, а генерирующее. как я понимаю функция tone использует таймер, который после заполнения (которое изменяется вторым параметром в скобочке настройке) меняет состояние на ножке (которая указывается первым параметром в скобочках настройки). 

я сейчас думаю обратиться к асемблеру, начать учить его. плохо то, что я не знаю как работают эти операторы, которые указаны в разделе "программирование" ардуино.  некоторые слова я вообще не понимаю, я даже незнаю как искать это в гугле, я просто беру выделяю и вставляю то, что вижу.  Я не хочу так делать, я написал сюда для того чтобы вы направили с какой стороны искать. Я благодарен ЕвгениюП за статью, что он предложил. Я прочту её, если есть еще что почитать, прошу, посылайте пожалуйста.

есть еще интересующий вопрос, хочу облегчить немного програму, неужели надо прописывать вывод данных на сериал и на лсиди в каждом цикле оператора иф

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
       //==============================================================
       

можно ли выводить данные на сериал и на лсиди после оператора иф, а не в каждом. если нет, то оставлю как есть, просто я вытаскивал их из циклов иф, но на дисплее ничего.... вот как то так.

b707
Offline
Зарегистрирован: 26.05.2017

Anytcent пишет:

можно ли выводить данные на сериал и на лсиди после оператора иф, а не в каждом

можно. Для этого переменные, которые Вы выводите(скажем b4) - должны быть описаны снаружи операторв иф, например глобально. В вашем же коде переменная b4 описана внутри каждого иф заново, поэтому когда вы выходите за пределы цикла, выводить нечего.

Anytcent
Offline
Зарегистрирован: 16.07.2016
enum Prescalers {
	PRESCALER_1 = 1, PRESCALER_8 = 2, PRESCALER_64 = 3, PRESCALER_256 = 4, PRESCALER_1024 = 5
};

void setup() {
	uint8_t prescaler = PRESCALER_1024;
	uint16_t topValue = 65535;
	pinMode(9, OUTPUT);
	TCCR1A = 0x40;			// Инвертирование пина 9 по сравнению
	TCCR1B = 0x08 | prescaler;	// Установить СТС режим и делитель частоты
	OCR1A = topValue;		// установить TOP равным topValue
}

void loop() {}

расскажите какой прескаллер использовать лучше ичто мне вбить в интернете для того чтобы понять что такое TCCR1A=0x40. откуда взято 0х40. я искал в даташите, в статьях о таймерах, но не могу понять. просто я хочу использовать еще 1 таймер, я буду читать еще, но подскажите что мне искать...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Anytcent пишет:

расскажите какой прескаллер использовать лучше

Там в статье есть калькулятор. Запустите, он скажет. Из тех, что он предложит, используйте любой.

Anytcent пишет:

ичто мне вбить в интернете для того чтобы понять что такое TCCR1A=0x40. 

https://drive.google.com/open?id=0B9r7cRXQ4DU4YVdhcDhadUI0bFE Разделы 15-18 как раз про все таймеры.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Anytcent пишет:

что мне вбить в интернете для того чтобы понять что такое 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 конфигурационных регистров - совсем удавиться придется?

Anytcent
Offline
Зарегистрирован: 16.07.2016

b707 пишет:

Anytcent пишет:

можно ли выводить данные на сериал и на лсиди после оператора иф, а не в каждом

можно. Для этого переменные, которые Вы выводите(скажем b4) - должны быть описаны снаружи операторв иф, например глобально. В вашем же коде переменная b4 описана внутри каждого иф заново, поэтому когда вы выходите за пределы цикла, выводить нечего.

большое спасибо! программа стала меньше на много. Теперь и ориентироваться в ней проще. Правда спасибо вам большое.

сейчас получилось сделать так, что бы программа выводила  расчитанные данные в виде частоты на пин9 и пин 11(просто так вышло, не критично). импульсы в виде маендра нужной частоты, теперь  хочу эти импульсы сделать кротковременными(ну типо одновибратора).  почитаю еще, если есть идеи говорите буду читать и учиться.

// программа инклинометрии

// ноги датчика         ардуино
// 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);
//====================================================================

enum Prescalers {
  PRESCALER_1 = 1, PRESCALER_8 = 2, PRESCALER_64 = 3, PRESCALER_256 = 4, PRESCALER_1024 = 5
};

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>){-606,   -725,   -369}; // данные калибровки осей X Y Z
  compass.m_max = (LSM303::vector<int16_t>){+614,   +529,   +711}; // данные калибровки осей 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);

//=================================================================
    //присваиваем переменным значения акселерометра
    ax = compass.a.x;
    ay = compass.a.y; 
    az = compass.a.z;
    m = heading; // это собственно азимут который определяет на сколько градусов повернут корпус датчика
//================================================================

//================================================================
// расчет в первом полушарие полушарии от 0 до 180 градусов    
//================================================================
    if (ax > 0) //если значения оси X больше ноля
{           
            //====================================================
            // расчет в первом квадранте от 0 до 90 градусов это если +X +Y
            //====================================================
            if (ay > 0) //если хначения оси Y больше ноля 
       {    
      
            b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы
            b2 = (((atan((sqrt(sq(ax)))/sqrt(sq(ay)))))*180)/3.14; // расчет угла проекции вектора относительно оси Y. переменные возводятся в квадрат, а потом выводятся из него для выведения их модуля
            b3 = b2 + m; // здесь идет сложения углов для определения в какую сторону наклонен датчик(азимут наклона)
            
                 if (b3 > 359) // если сумма больше 360 градусов 
            {
                 b4 = b3 - 359; // то просто от этой суммы вычитывается 360
                 
            }
                 else // а если нет, то b4 = b3
            {
                 b4 = b3;
                 
            }
            
                    
       }   
       // конец расчета в первом квадранте от 0 до 90 градусов это если +X +Y
       //==============================================================
       
            //=========================================================
            // расчет во втором квадранте от 90 до 180 градусов это если +X -Y
            //=========================================================
            else //если значения оси Y меньше ноля
       {   
         
            b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы
            b2 = ((((atan((sqrt(sq(ay)))/sqrt(sq(ax)))))*180)/3.14)+90; // расчет угла проекции вектора относительно оси X, т.к. мы уже во втором квадранте и прибавляем к полученным данным 90
            b3 = b2 + m; // здесь идет сложения углов, для определения в какую сторону наклонен датчик
                 
                 if (b3 > 359) // если сумма больше 360 градусов
            {
                 b4 = b3 - 359; // // то просто от этой суммы вычитывается 360
                 
            }
                 else // а если нет, то b4 = b3
            {
                 b4 = b3;
                  
            }
         
                        
       }
       // конец расчета во втором квадранте от 90 до 180 градусов это если +X -Y
       //==============================================================
       
}
// конец расчета в первом полушарии от 0 до 180 градусов 
//================================================================


//================================================================
// расчет во втором полушарие полушарии от 180 до 360 градусов
//================================================================
     if (ax < 0) //если значения оси X меньше ноля
{        
         //=======================================================
         // расчет в третьем квадранте от 180 до 270 градусов это если -X -Y
         //=======================================================
         if (ay < 0) //если значения оси Y меньше ноля 
    {    
         b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы
         b2 = ((((atan((sqrt(sq(ax)))/sqrt(sq(ay)))))*180)/3.14)+180; // расчет угла проекции вектора относительно оси X, т.к. мы уже в третьем квадранте и прибавляем к полученным данным 180
         b3 = b2 + m; // здесь идет сложения углов, для определения в какую сторону наклонен датчик
              
              if (b3 > 359) // если сумма больше 360 градусов
         {
              b4 = b3 - 359; // то просто от этой суммы вычитывается 360
               
         }
              else // а если нет, то b4 = b3
         {
              b4 = b3;
              
         }  
                   
    } 
    // конец расчета в третьем квадранте от 180 до 270 градусов это если -X -Y
    //==============================================================  

         //=========================================================
         // расчет в четвёртом квадранте от 270 до 360 градусов это если -X +Y
         //=========================================================
         else //если значения оси Y больше ноля
    {   
         
         b1 = ((acos(az / sqrt(sq(ax) + sq(ay) + sq(az)))) * 180)/3.14; // расчет зенитного угла и превращение его из радианов в градусы
         b2 = ((((atan((sqrt(sq(ay)))/sqrt(sq(ax)))))*180)/3.14)+270; // расчет угла проекции вектора относительно оси X, т.к. мы уже в третьем квадранте и прибавляем к полученным данным 270
         b3 = b2 + m; // здесь идет сложения углов, для определения в какую сторону наклонен датчик
              
              if (b3 > 359) // если сумма больше 360 градусов
         {
              b4 = b3 - 359; // то просто от этой суммы вычитывается 360 
               
         }
              else // а если нет, то b4 = b3
         {
              b4 = b3;
              
         } 
      
    }
    // конец расчета в четвертом квадранте от 270 до 360 градусов это если -X +Y
    //==============================================================  
}
              // выводится посчитанный азимут
              Serial.print("azimut naklona4 =  ");
              Serial.println(b4);
              lcd.setCursor(0, 0);
              lcd.print("azim=");
              lcd.print(b4);
              lcd.print(" ");
              cha = b4 * 100;         
              tone(11, cha);
           
              
  // выводится посчитанный зенитный угол
  Serial.print("ugol naklona =  ");
  Serial.println(b1);
  lcd.setCursor(0, 2);
  lcd.print("zen=");
  lcd.print(b1);
  lcd.print(" "); 
      chu = (8000000 / (b1*100))-1;
      uint8_t prescaler = PRESCALER_1;
      uint16_t topValue = chu;
      pinMode(9, OUTPUT);
      TCCR1A = 0x40;      // Инвертирование пина 9 по сравнению
      TCCR1B = 0x08 | prescaler;  // Установить СТС режим и делитель частоты
      OCR1A = topValue;   // установить TOP равным topValue

}

зенитный угол выводится на пин 9 по тому методу, что описано в статье ЕвгенийП "Этюды для начинающих: blink и без delay, и без millis", а азимут(азимут наклона) выводится функцией tone на пин 11.