Магнитометр

fedoroff_alexander
Offline
Зарегистрирован: 12.04.2015

Простейший домашний магнитометр с двумя устройствами типа компас. Написан с использованием свободно распространяемого в Интернет кода и библиотек.

Весь проект со схемами в ZIP файле можно скачать по ссылке. Просто не увидел, что здесь можно вставлять архивные файлы.

https://fedoroffalexander.wixsite.com/smart/esp-8266

fedoroff_alexander
Offline
Зарегистрирован: 12.04.2015

Забыл вставить исходный код

/*
   Домашний магнетометр
   Модуль ESP32 WROOM. В менеджере плат - DOIT ESP32 DEVKIT V1. Версия для ESP32 - Espresiif system v 1.0.6
   Arduino IDE 1.8.13
*/
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define sizeTrend 30//количество точек в тренде
#define OLED_MOSI   23
#define OLED_CLK    18
#define OLED_DC     16
#define OLED_CS     5 //Для других SPI устойств CS должен быть другим
#define OLED_RESET  17
#define BUZZER_PIN 2
#define BUZZER_CHANNEL 0

#include <Tone32.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
//#include <DFRobot_QMC5883.h>
#include <Adafruit_LIS3MDL.h>
#include "GyverTimer.h"

int Freq_signal = 100;
GTimer myTimer(MS, Freq_signal);    // создать миллисекундный таймер
//GTimer myTimer(US);    // US - микросекундный
#include "GyverButton.h"
// Варианты инициализации кнопок:
// GButton btn;// без привязки к пину (виртуальная кнопка) и без указания типа (по умолч. HIGH_PULL и NORM_OPEN)
// GButton btn(пин);// с привязкой к пину и без указания типа (по умолч. HIGH_PULL и NORM_OPEN)
// GButton btn(пин, тип подключ.);// с привязкой к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и без указания типа кнопки (по умолч. NORM_OPEN)
// GButton btn(пин, тип подключ., тип кнопки);// с привязкой к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и типа кнопки (NORM_OPEN / NORM_CLOSE)
// GButton btn(BTN_NO_BTN_PIN, тип подключ., тип кнопки);// без привязки к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и типа кнопки (NORM_OPEN / NORM_CLOSE)

//DFRobot_QMC5883 compass1;
//DFRobot_QMC5883 compass2;
//Декларируем две I2C шины

/*int *in1 = new int[sizeTrend+1]; 	//массив для первого тренда
  int *in2 = new int[sizeTrend+1];	//массив для второго тренда
  int *in3 = new int[sizeTrend+1];	//массив для второго тренда*/
int in1[sizeTrend];	//массив для первого тренда
int in2[sizeTrend];	//массив для второго тренда
int in3[sizeTrend];	//массив для второго тренда
const int LED = 15; //синий светодиод
//int r=0;
int x, y, z, t; int _x, _y, _z, _t;
int X1, Y1, Z1; int X2, Y2, Z2;
int Min, Max; int MIN, MAX; int MIN2, MAX2;

int cnt_LeftRight = 1; 		//Счетчик перемещения по горизонтальному меню
int cnt_UpDown = 1; 		//Счетчик перемещения по вертикальному меню
int cnt_UpDownSensor = 1; 	//Счетчик перемещения по вертикальному меню для сенсоров
bool flag_UpDownSensor = true;

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
                         OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
GButton btn_Left(27);
GButton btn_Right(12);
GButton btn_Up(13);
GButton btn_Down(14);
GButton btn_Enter(26);
Adafruit_LIS3MDL compass1;
Adafruit_LIS3MDL compass2;

bool menu_OnOff = false; bool menu_Senor = true;
char *Coordinats = "ZXY"; int cnt_Coordinats = 1;
int TrigerMINz = 0; int TrigerMAXz = 0;
int MINz = 400; int MAXz = -400;
int Volume = 0; int freq = 600; int channel = 0;
int resolution = 8;
int Buzzer = 0; int Algoritm = 1; int Chanel = 1;
int Raznica = 0; int Porog = 0; int Param1 = 0; float Param2 = 0.0;

//конвертирование данных из массива для варианта приема байтовых значений
int convert(int y, int mn, int mx, byte yTrend, byte heightTrend, int *buf ) {
  int ny = y;
  ny = map(ny, mn, mx, heightTrend - 1 + yTrend, yTrend);
  //ny=map(ny,mn,mx,yTrend,heightTrend-1+yTrend);
  return ny;
}

//отрисовка тренда (ширина, высота, x координата, y координата, аналоговый вход, массив для хранения измерений)
void drawTrend(int widthTrend, int heightTrend, int xTrend, int yTrend, int cn, int *buf) {
  buf[sizeTrend - 1] = cn; //добавляем новое значение
  int oldX = 0;
  int oldY = 0 + yTrend;
  int mn = MINz; //для поиска минимума
  int mx = MAXz; //для поиска максимума
  double k = 0.0;
  //сдвигаем график
  for  (int x = 0; x < (sizeTrend - 1); x++) {
    buf[x] = buf[x + 1]; //переписываем в текущюю ячейку массива данные из следующей
  }

  //поиск мин и макс
  for (int i = 0; i < sizeTrend; i++) { //пробегаем по массиву
    if (buf[i] > mx) { //если значение в ячейке больше макс
      mx = buf[i]; //то макс = содержимому ячейки
    }
    if (buf[i] < mn) { //если значение в ячейке меньше мин
      mn = buf[i]; //то мин = содержимому ячейки
    }
  }
  if (mn == mx) { //если мин=макс
    mx = mn + 1; //устанавливаем макс+=1
    mn = mn - 1; //мин-=1
  }

  //формирование буфера вывода
  for (int x = 0; x < sizeTrend - 1; x++) { //Х координата
    int y = convert(buf[x], mn, mx, yTrend, heightTrend, buf); //Y координата
    int nxt_x = map(x, 0, sizeTrend - 1, 0, widthTrend);
    //отрисовка тренда
    display.drawLine(xTrend + oldX, oldY, xTrend + nxt_x, y, WHITE);
    oldX = nxt_x;
    oldY = y;
  }
  
  //отрисовка рамки
  display.drawRect(xTrend, yTrend, widthTrend, heightTrend, WHITE);

  //вывод минимума и максимума на экран
  display.setCursor(xTrend + widthTrend + 3, yTrend);
  display.println(mx); Max = mx;
  display.setCursor(xTrend + widthTrend + 3, yTrend + heightTrend - 8);
  display.println(mn); Min = mn;
  display.setCursor(xTrend + widthTrend + 3, yTrend + (heightTrend / 2) - 4);
  display.println(buf[sizeTrend - 1]); //текущее
  oldX = 0; //чтобы новая линия сначала тренда отрисовывалась
  oldY = convert(buf[0], mn, mx, yTrend, heightTrend, buf);

}

//Опрашиваем кнопки по прерыванию*************************************************************************
void isr_Left() {
  btn_Left.tick();
}
void isr_Right() {
  btn_Right.tick();
}
void isr__Up() {
  btn_Up.tick();
}
void isr__Down() {
  btn_Down.tick();
}
void isr__Enter() {
  btn_Enter.tick();
}
//********************************************************************************************************

void setup() {
  Serial.begin(115200);
  //memset(in1, 0x0, sizeTrend);
  //memset(in2, 0x0, sizeTrend);
  //memset(in3, 0x0, sizeTrend);
  pinMode(LED, OUTPUT); //синий светодиод тревоги
  digitalWrite(LED, LOW);
  pinMode(19, OUTPUT); //красный светодиод тревоги
  digitalWrite(19, LOW);

  //Настройка кнопок**************************************************************************************
  // настройка антидребезга (по умолчанию 80 мс)
  // настройка таймаута на удержание (по умолчанию 500 мс)
  btn_Left.setDebounce(50); btn_Left.setTimeout(300);
  btn_Right.setDebounce(50); btn_Right.setTimeout(300);
  btn_Up.setDebounce(50); btn_Up.setTimeout(300);
  btn_Down.setDebounce(50); btn_Down.setTimeout(300);
  btn_Enter.setDebounce(50); btn_Enter.setTimeout(300);
  //Кнопки настроены***************************************************************************************

  //Init display ******************************************************************************************
  if (!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
  }
  display.display();
  delay(1000);
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE); 	// Draw white text
  display.cp437(true);         			// Use full 256 char 'Code Page 437' font
  display.println("Init...");
  display.println("Display SSD1306");
  //End Init display ****************************************************************************************

  // Initialize magnetic sensors  LIS3MDL********************************************************************
  if (compass1.begin_I2C(0x1E)) {          // hardware I2C mode, can pass in address & alt Wire 0x1E
    display.println("Sensor1 Ok");
  }
  if (compass2.begin_I2C(0x1C)) {          // hardware I2C mode, can pass in address & alt Wire0x1C
    display.println("Sensor2 Ok");
  }
  // End initialize  LIS3MDL*********************************************************************************

  // Initialize magnetic sensors HMC5883, QMC5883, VCM5883L**************************************************
  /*while (!compass1.begin()) {
    //Serial.println("Could not find a valid magnetic sensor, check wiring!");
    display.println("No magnetic sensor1");
    delay(500);
    }

    if (compass1.isHMC()) {
    //Serial.println("Sensor1 HMC5883");
    display.println("Sensor1 HMC5883");
    //compass1.setRange(HMC5883L_RANGE_1_3GA);
    //compass1.setMeasurementMode(HMC5883L_CONTINOUS);
    //compass1.setDataRate(HMC5883L_DATARATE_15HZ);
    //compass1.setSamples(HMC5883L_SAMPLES_8);
    } else if (compass1.isQMC()) {
    //Serial.println("Sensor1 QMC5883");
    display.println("Sensor1 QMC5883");
    compass1.setRange(QMC5883_RANGE_2GA);
    //compass1.setMeasurementMode(QMC5883_CONTINOUS);
    //compass1.setDataRate(QMC5883_DATARATE_50HZ);
    //compass1.setSamples(QMC5883_SAMPLES_8);
    } else if (compass1.isVCM()) {
    //Serial.println("Sensor1 VCM5883L");
    display.println("Sensor1 VCM5883L");
    //compass1.setMeasurementMode(VCM5883L_CONTINOUS);
    //compass1.setDataRate(VCM5883L_DATARATE_200HZ);
    } else display.println("No sensors1");

    while (!compass2.begin()){
    //Serial.println("Could not find a valid magnetic sensor, check wiring!");
    display.println("No magnetic sensor1");
    delay(500);
    }
    if (compass2.isHMC()){
    //Serial.println("Sensor2 HMC5883");
    display.println("Sensor2 HMC5883");
    //compass2.setRange(HMC5883L_RANGE_1_3GA);
    //compass2.setMeasurementMode(HMC5883L_CONTINOUS);
    //compass2.setDataRate(HMC5883L_DATARATE_15HZ);
    //compass2.setSamples(HMC5883L_SAMPLES_8);
    }else if (compass2.isQMC()){
    //Serial.println("Sensor2 QMC5883");
    display.println("Sensor2 QMC5883");
    compass2.setRange(QMC5883_RANGE_2GA);
    //compass2.setMeasurementMode(QMC5883_CONTINOUS);
    //compass2.setDataRate(QMC5883_DATARATE_50HZ);
    //compass2.setSamples(QMC5883_SAMPLES_8);
    }else if (compass2.isVCM()){
    //Serial.println("Sensor VCM5883L");
    display.println("Sensor2 VCM5883L");
    //compass2.setMeasurementMode(VCM5883L_CONTINOUS);
    //compass2.setDataRate(VCM5883L_DATARATE_200HZ);
    } else display.println("No sensors2");*/
  // End initialize HMC5883, QMC5883, VCM5883L *************************************************

  display.display();
  delay(4000);
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE); 	// Draw white text
  display.cp437(true);         			// Use full 256 char 'Code Page 437' font

  //Вывести Номер сенсора-датчика
  for (int cntr = 1; cntr < 9; cntr++) {
    display.clearDisplay(); 			//Очистить буфер дисплея и картинку
    display.setCursor(0, 0);  display.setTextSize(cntr); display.print(cnt_UpDownSensor);
    display.display();
    delay(100);
  }
  display.setTextSize(1);
  display.clearDisplay();
  display.display();

  //Инициализация зумера тревоги
  ledcSetup(channel, freq, resolution);
  ledcAttachPin(2, channel);
}

void loop() {
  btn_Left.tick();  // опрашиваем в скетче, иначе не будут работать проверки по времени!
  btn_Right.tick();
  btn_Up.tick();
  btn_Down.tick();
  btn_Enter.tick();
  //Раскоментировать для тестирования кнопок*****************************************************
  /*if (btn_Left.isSingle()) Serial.println("Single Left");  	// проверка на один клик
    if (btn_Left.hasClicks())                                	// проверка на наличие нажатий
    Serial.println(btn_Left.getClicks());                  		// получить (и вывести) число нажатий
    if (btn_Right.isSingle()) Serial.println("Single Right");   // проверка на один клик
    if (btn_Right.hasClicks())                                	// проверка на наличие нажатий
    Serial.println(btn_Right.getClicks());                  	// получить (и вывести) число нажатий*/
  //***********************************************************************************************

  if (myTimer.isReady()) {
    display.clearDisplay(); //Очистить буфер дисплея и картинку
    
    //МЕНЮ On/Off***************************************************************************************
    if (btn_Enter.hasClicks()) {
      menu_OnOff = !menu_OnOff;
      menu_Senor = !menu_OnOff;
    }
    //МЕНЮ On/Off end***********************************************************************************

    //Установка порядка и размеров графиков по координатом на экране************************************

    //Клавиша ВЛЕВО*************************************************************************************
    if (btn_Left.hasClicks() && menu_OnOff) {
      --cnt_LeftRight;
      int clicks = btn_Left.getClicks(); //число кликов
      if (clicks != 1) cnt_LeftRight = clicks;
    }
    //Отработано Клавиша ВЛЕВО**************************************************************************

    //Клавиша ВПРАВО************************************************************************************
    if (btn_Right.hasClicks() && menu_OnOff) {
      ++cnt_LeftRight;
      //--cnt_UpDownSensor;
      int clicks = btn_Right.getClicks(); //число кликов
      if (clicks != 1) cnt_LeftRight = clicks;
    }
    //Отработано Клавиша ВПРАВО*************************************************************************

    //Клавиша ВВЕРХ, cnt_UpDown = количеству пунктов вертикального меню*********************************
    if (btn_Up.hasClicks() && menu_OnOff) {
      --cnt_UpDown;
      int clicks = btn_Up.getClicks(); //число кликов
      if (clicks != 1) cnt_UpDown = clicks;
    }
    //end ВВЕРХ******************************************************************************************

    //Клавиша ВНИЗ***************************************************************************************
    if (btn_Down.hasClicks() && menu_OnOff) {
      ++cnt_UpDown;
      int clicks = btn_Down.getClicks(); //число кликов
      if (clicks != 1) cnt_UpDown = clicks;
    }
    //end Клавиша ВНИЗ************************************************************************************

    //Обрабатываем ВВЕРХ-ВНИЗ*****************************************************************************

    //Показать номер сенсора******************************************************************************
    if (!menu_OnOff) {
      if (btn_Up.hasClicks() && !menu_OnOff) {
        --cnt_UpDownSensor;
        flag_UpDownSensor = !flag_UpDownSensor;
        if (cnt_UpDownSensor < 1) cnt_UpDownSensor = 2;
        for (int cntr = 1; cntr < 9; cntr++) {
          display.clearDisplay(); //Очистить буфер дисплея и картинку
          display.setCursor(0, 0);  display.setTextSize(cntr); display.print(cnt_UpDownSensor);
          display.display();
          delay(50);
        }
        display.setTextSize(1);
        display.clearDisplay();
        display.display();
      }

      if (btn_Down.hasClicks() && !menu_OnOff) {
        ++cnt_UpDownSensor;
        flag_UpDownSensor = !flag_UpDownSensor;
        if (cnt_UpDownSensor > 2) cnt_UpDownSensor = 1;
        for (int cntr = 1; cntr < 9; cntr++) {
          display.clearDisplay(); //Очистить буфер дисплея и картинку
          display.setCursor(0, 0);  display.setTextSize(cntr); display.print(cnt_UpDownSensor);
          display.display();
          delay(50);
        }
        display.setTextSize(1);
        display.clearDisplay();
        display.display();
      }
    }
    //Показали номер сенсора******************************************************************************

    //Меню************************************************************************************************
    if (menu_OnOff) {
      if (cnt_UpDown < 1) cnt_UpDown = 6;
      if (cnt_UpDown > 6) cnt_UpDown = 1;
      switch (cnt_UpDown) {
        case 1:
          if (btn_Right.hasClicks()) cnt_Coordinats += 1;
          if (cnt_Coordinats > 3) cnt_Coordinats = 1;
          if (btn_Left.hasClicks()) cnt_Coordinats -= 1;
          if (cnt_Coordinats < 1) cnt_Coordinats = 3;
          if (cnt_Coordinats == 1) {
            Coordinats = "";
            Coordinats = "ZXY";
          }
          if (cnt_Coordinats == 2) {
            Coordinats = "";
            Coordinats = "YZX";
          }
          if (cnt_Coordinats == 3) {
            Coordinats = "";
            Coordinats = "XYZ";
          }
          //display.clearDisplay();
          display.setCursor(5, 0);  display.printf("> %-12s  %s", "Coordinats", Coordinats);
          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
          display.display();
          break;
        case 2:
          if (btn_Right.hasClicks()) {
            int clicks = btn_Right.getClicks(); //число кликов
            if (clicks == 1) ++TrigerMAXz;
            if (clicks == 2) TrigerMAXz += 10;
            if (clicks == 3) TrigerMAXz += 100;
            if (clicks == 4) TrigerMAXz += 1000;
          }
          if (btn_Left.hasClicks()) {
            int clicks = btn_Left.getClicks(); //число кликов
            if (clicks == 1) --TrigerMAXz;
            if (clicks == 2) TrigerMAXz -= 10;
            if (clicks == 3) TrigerMAXz -= 100;
            if (clicks == 4) TrigerMAXz -= 1000;
          }
          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
          display.setCursor(5, 10); display.printf("> %-12s  %d", "Triger MAXz", TrigerMAXz);
          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
          display.display();
          break;
        case 3:
          if (btn_Right.hasClicks()) {
            int clicks = btn_Right.getClicks(); //число кликов
            if (clicks == 1) ++TrigerMINz;
            if (clicks == 2) TrigerMINz += 10;
            if (clicks == 3) TrigerMINz += 100;
            if (clicks == 4) TrigerMINz += 1000;
          }
          if (btn_Left.hasClicks()) {
            int clicks = btn_Left.getClicks(); //число кликов
            if (clicks == 1) --TrigerMINz;
            if (clicks == 2) TrigerMINz -= 10;
            if (clicks == 3) TrigerMINz -= 100;
            if (clicks == 4) TrigerMINz -= 1000;
          }
          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
          display.setCursor(5, 20); display.printf("> %-12s  %d", "Triger MINz", TrigerMINz);
          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
          display.display();
          break;
        case 4:
          if (btn_Right.hasClicks()) {
            int clicks = btn_Right.getClicks(); //число кликов
            if (++Buzzer > 1) Buzzer = 0;
          }
          if (btn_Left.hasClicks()) {
            int clicks = btn_Left.getClicks(); //число кликов
            if (--Buzzer < 0) Buzzer = 1;
          }
          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
          display.setCursor(5, 30); display.printf("> %-12s  %d", "Buzzer", Buzzer);
          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
          display.display();
          break;
        case 5:
          if (btn_Right.hasClicks()) {
            int clicks = btn_Right.getClicks(); //число кликов
            if (++Algoritm > 2) Algoritm = 1;
          }
          if (btn_Left.hasClicks()) {
            if (--Algoritm < 1) Algoritm = 2;
          }
          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
          display.setCursor(5, 40); display.printf("> %-12s  %d", "Algoritm", Algoritm);
          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
          display.display();
          break;
        case 6:
          if (btn_Right.hasClicks()) {
            int clicks = btn_Right.getClicks(); //число кликов
            if (++cnt_UpDownSensor > 2) cnt_UpDownSensor = 1;
          }
          if (btn_Left.hasClicks()) {
            int clicks = btn_Left.getClicks(); //число кликов
            if (--cnt_UpDownSensor < 1) cnt_UpDownSensor = 2;
          }
          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
          display.setCursor(5, 50); display.printf("> %-12s  %d", "Sensor", cnt_UpDownSensor);
          display.display();
          break;
      }
    }
    //end ВВЕРХ-ВНИЗ Меню*********************************************************************************

    //Обрабатываем ВЛЕВО-ВПРАВО***************************************************************************
    if (!menu_OnOff) {
      if (btn_Right.hasClicks()) cnt_Coordinats += 1;
      if (cnt_Coordinats > 3) cnt_Coordinats = 1;
      if (btn_Left.hasClicks()) cnt_Coordinats -= 1;
      if (cnt_Coordinats < 1) cnt_Coordinats = 3;
      if (cnt_UpDownSensor == 1) { //Работаем с 1 сенсором
        _x = X1; _y = Y1; _z = Z1;
      }
      if (cnt_UpDownSensor == 2) { //Работаем с 2 сенсором
        _x = X2; _y = Y2; _z = Z2;
      }
      switch (cnt_Coordinats) {
        case 1:
          Coordinats = ""; Coordinats = "ZXY";
          display.setCursor(0, 25); display.println("z");
          display.setCursor(25, 30); display.println("x");
          display.setCursor(90, 30); display.println("y");
          //int Raznica = 0; int Porog = 0; int Param1 = 0; float Param2 = 0.0;
          if (Algoritm == 2) {
            display.setCursor(10, 25);
            display.printf("[%d] [%d] [%.1f]", Raznica,Porog,Param2);
          }
          drawTrend(95, 25, 0, 0, _z, in1); //вывод 1 тренда по данным из массива in1-Z
          //Запись в переменные в зависимости от выбранного канала датчика cnt_UpDownSensor по Z**********
          if (cnt_UpDownSensor == 1) {
            MIN = Min; MAX = Max;
          }
          if (cnt_UpDownSensor == 2) {
            MIN2 = Min; MAX2 = Max;
          }
          //***********************************************************************************************
          drawTrend(30, 25, 0, 39, _x, in2); //вывод второго по данным из in2-X
          drawTrend(34, 25, 60, 39, _y, in3); //вывод третьего по данным из in3-Y
          display.display();
          break;
        case 2:
          Coordinats = ""; Coordinats = "YZX";
          //display.clearDisplay();
          display.setCursor(0, 25); display.println("y");
          display.setCursor(25, 30); display.println("z");
          display.setCursor(90, 30); display.println("x");
          if (Algoritm == 2) {
            display.setCursor(10, 25);
            display.printf("[%d] [%d] [%.1f]", Raznica,Porog,Param2);
          }
          drawTrend(95, 25, 0, 0, _y, in3); //вывод 1 тренда по данным из массива in3-Y
          drawTrend(30, 25, 0, 39, _z, in1); //вывод второго по данным из in1-Z
          //Запись в переменные в зависимости от выбранного канала датчика cnt_UpDownSensor по Z************
          //MIN2 = Min; MAX2 = Max; X2 = x; Y2 = y; Z2 = z;
          if (cnt_UpDownSensor == 1) {
            MIN = Min; MAX = Max;
          }
          if (cnt_UpDownSensor == 2) {
            MIN2 = Min; MAX2 = Max;
          }
          //*************************************************************************************************
          drawTrend(34, 25, 60, 39, _x, in2); //вывод третьего по данным из in2-X
          display.display();
          break;
        case 3:
          Coordinats = ""; Coordinats = "XYZ";
          //display.clearDisplay();
          display.setCursor(0, 25); display.println("x");
          display.setCursor(25, 30); display.println("y");
          display.setCursor(90, 30); display.println("z");
          if (Algoritm == 2) {
            display.setCursor(10, 25);
            display.printf("[%d] [%d] [%.1f]", Raznica,Porog,Param2);
          }
          drawTrend(95, 25, 0, 0, _x, in2); //вывод 1 тренда по данным из массива in2-X
          drawTrend(30, 25, 0, 39, _y, in3); //вывод второго по данным из in3-Y
          drawTrend(34, 25, 60, 39, _z, in1); //вывод третьего по данным из in1-Z
          if (cnt_UpDownSensor == 1) {
            MIN = Min; MAX = Max;
          }
          if (cnt_UpDownSensor == 2) {
            MIN2 = Min; MAX2 = Max;
          }
          display.display();
          break;

      }
    }
    display.clearDisplay(); //Очистить буфер дисплея и картинку
    //display.display();
    //Отработали ВЛЕВО-ВПРАВО*****************************************************************************

    //выводим в плоттер по последовательному порту в зависимости от выбранного датчика*******
    //После отладки закоментировать блок
    if (cnt_UpDownSensor == 1) {
      Serial.print(" X1:");
      Serial.print(X1);
      Serial.print(" Y1:");
      Serial.print(Y1);
      Serial.print(" Z1:");
      Serial.println(Z1);
    }
    if (cnt_UpDownSensor == 2) {
      Serial.print(" X2:");
      Serial.print(X2);
      Serial.print(" Y2:");
      Serial.print(Y2);
      Serial.print(" Z2:");
      Serial.println(Z2);
    }

    //плоттер end****************************************************************************************
    myTimer.start(); //Перезапуск таймера
  }
  
  /*if (cnt_UpDownSensor == 1) {    //Первый I2C датчик QMC5883
      Vector mag = compass1.readRaw();// Читаем значения датчика. При другой библиотеке и датчике заменить
      //x = mag.XAxis;
      //y = mag.YAxis;
      //z = mag.ZAxis;
      X1 = mag.XAxis;
      Y1 = mag.YAxis;
      Z1 = mag.ZAxis;
      }
      if (cnt_UpDownSensor == 2) {    //Второй I2C датчик QMC5883
      Vector mag = compass1.readRaw();// Читаем значения датчика. При другой библиотеке и датчике заменить
      X2 = mag.XAxis;
      Y2 = mag.YAxis;
      Z2 = mag.ZAxis;
      }*/
    sensors_event_t event1;
    sensors_event_t event2;
    //if (cnt_UpDownSensor == 1) {    //Первый I2C датчик
    /*compass1.read(); //в Гаусах
      X1 = compass1.x;
      Y1 = compass1.y;
      Z1 = compass1.z;*/
    compass1.getEvent(&event1); //в Тесла
    X1 = event1.magnetic.x;
    Y1 = event1.magnetic.y;
    Z1 = event1.magnetic.z;
    //}
    //if (cnt_UpDownSensor == 2) {    //Второй I2C датчик
    /*compass2.read(); //в Гаусах
      X2 = compass2.x;
      Y2 = compass2.y;
      Z2 = compass2.z;*/
    compass2.getEvent(&event2); //в Тесла
    X2 = event2.magnetic.x;
    Y2 = event2.magnetic.y;
    Z2 = event2.magnetic.z;
    //}
    /*Тест для датчика Амперка
       Serial.print(compass1.readMagneticGaussX());
      Serial.print("\t\t");
      // Выводим напряженность магнитного поля в Гауссах по оси Y
      Serial.print(compass1.readMagneticGaussY());
      Serial.print("\t\t");
      // Выводим напряженность магнитного поля в Гауссах по оси Z
      Serial.println(compass1.readMagneticGaussZ());
      Serial.println("=================================================");
    */
  
  //*****************************************************************************************************
  //*****************************************************************************************************
  //*****************************************************************************************************
  /*
       БЛОК МОЙ КОД
       ЦИКЛЫ ДЕЛАТЬ НЕЛЬЗЯ (крайне не рекомендуется)!!!. СОБЪЕТСЯ ЧАСТОТА ОПРОСА СИГНАЛА и скорость вывода на экран.
       Чем больше интервал частоты опроса (реже опрашиваем), тем больше мы срезаем ПОМЕХ.
       (int) Freq_signal = 100 милисекунд. Можете изменить частоту опроса датчиков
       Здесь пишем алгоритмы обработки сигнала...
       Когда и при каких условиях срабатывают тригеры...
       Когда и как срабатывает световая и звуковая сигнализация...
       (int) TrigerMINz - устанавливается в Меню вручную. Граница срабатывания по оси Z
       (int) TrigerMAXz - устанавливается в Меню вручную. Граница срабатывания по оси Z
       Данные с выбранного в Меню датчика реализовано только по оси Z
       Значение cnt_UpDownSensor == 1 - Первый I2C датчик
       Значение cnt_UpDownSensor == 2 - Второй I2C датчик
       В зависимости от cnt_UpDownSensor в x, y, z будут отражены данные от 1го или 2го датчика
       (int) x - значение 1(2) датчика по X
       (int) y - значение 1(2) датчика по Y
       (int) z - значение 1(2) датчика по Z
       (int) X1, Y1, Z1 - переменные для экспериментов по первому датчику
       (int) X2, Y2, Z2 - переменные для экспериментов по второму датчику
       (int) MIN, MAX - переменные для экспериментов по первому датчику установленные программно
       (int) MIN2, MAX2 - переменные для экспериментов по второму датчику установленные программно
       (int) Algoritm - переключатель алгоритма обработки значений датчика
       (int) LED - Адрес светодиода 15 (D15)
       (int) BUZZER_PIN - Адрес зумера 2 (D2)

       (int) Raznica = 0; (int) Porog = 0; (int) Param1 = 0; (float) Param2 = 0.0;
	   Алгоритм работы с двумя датчиками

		Dat1 - показания первого датчика после усреднения.
		Dat2 - показания второго датчика после усреднения.
		Porog - порог срабатывания (настраивается кнопками на плате).
		Raznica - разница между показаниями двух датчиков.

		Прибор срабатывает (подает звуковой сигнал) если Raznica по модулю (без учета знака +-) >= Porog.
		if (abs(Dat1 - Dat2) >= Porog) { даем сигнал на динамик }

		Усреднение данных - Экспоненциальное бегущее среднее

		float k = 0.1; // коэффициент фильтрации, 0.0-1.0
		// бегущее среднее
		float expRunningAverage(float newVal) {
			static float filVal = 0;
			filVal += (newVal - filVal) * k;
			return filVal;
		}
		"Сила" фильтра настраивается коэффициентом (0.0 – 1.0). Чем он меньше, тем плавнее фильтр

       В ДРУГОЙ КОД НЕ ЛЕЗЕМ!!! Внутри БЛОКА все что угодно. Делаем копию БЛОКА!
  */
  //Отладка. Выводим в монитор последовательного порта. Мешает выводу в плоттер. После отладки закоментировать***
  //Serial.printf("X1    = %6d, Y1    = %6d, Z1  = %6d\n",X1, Y1, Z1);
  //Serial.printf("X2   = %6d, Y2   = %6d, Z2 = %6d\n",X2, Y2, Z2);
  //Serial.printf("MIN  = %6d, MAX  = %6d\n", MIN, MAX);
  //Serial.printf("MIN2 = %6d, MAX2 = %6d\n", MIN2, MAX2);
  //Монитор end***************************************************************************************************

  //Алгоритм 1. Обрабатывает данные минимального и максимального значения датчика по оси Z
  //включает/выключает синий светодиод (минимум), краный светодиод (максимум) и зуммер
  if (Algoritm == 1) {
    if (Z1 < TrigerMINz) {
      digitalWrite(LED, HIGH);
      if (Buzzer == 1) {
        //tone(BUZZER_PIN, NOTE_C4, 5, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_D4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_E4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_F4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_G4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_A4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        tone(BUZZER_PIN, NOTE_B4, 10, BUZZER_CHANNEL);
        noTone(BUZZER_PIN, BUZZER_CHANNEL);
      }
      else noTone(BUZZER_PIN, BUZZER_CHANNEL);
    }
    else digitalWrite(LED, LOW);

    if (Z1 > TrigerMAXz) {
      digitalWrite(19, HIGH);
      if (Buzzer == 1) {
        tone(BUZZER_PIN, NOTE_C4, 10, BUZZER_CHANNEL);
        noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_D4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_E4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_F4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_G4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_A4, 500, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //tone(BUZZER_PIN, NOTE_B4, 5, BUZZER_CHANNEL);
        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
      }
      else noTone(BUZZER_PIN, BUZZER_CHANNEL);
    }
    else digitalWrite(19, LOW);
  }

  //Алгоритм 2. Здесь исходный код Заказчика. Основаный на примере Алгоритм 1.
  //включает/выключает ... if (abs(Dat1 - Dat2) >= Porog) { даем сигнал на динамик }
    if (Algoritm == 2) {
    Raznica = 1; Porog = 2; Param1 = 3; Param2 = 4.0;
    if (Porog > TrigerMAXz) {
      digitalWrite(19, HIGH);
    }
    else digitalWrite(19, LOW);
    if (Porog > TrigerMAXz) {
      digitalWrite(LED, HIGH);
    }
    else digitalWrite(19, LOW);
  }

  /*
     Конец блока МОЙ КОД********************************************************************************
     В ДРУГОЙ КОД ВНЕ БЛОКА НЕ ЛЕЗЕМ!!!
  */
  //*****************************************************************************************************
  //*****************************************************************************************************
  //*****************************************************************************************************
}//Конец цикла Loop

 

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

Ну, хоть маленькое описание-то надо!

Чего измеряем, в каких попугаях,  в каком диапазоне, с какой точностью? Ну, чего ж ничего-то нет?

fedoroff_alexander
Offline
Зарегистрирован: 12.04.2015
     //if (cnt_UpDownSensor == 1) {    //Первый I2C датчик
635
    /*compass1.read(); //в Гаусах

    compass1.getEvent(&event1); //в Тесла

    //if (cnt_UpDownSensor == 2) {    //Второй I2C датчик
645
    /*compass2.read(); //в Гаусах

    compass2.getEvent(&event2); //в Тесла

    /*Тест для датчика Амперка
655
       Serial.print(compass1.readMagneticGaussX());
656
      Serial.print("\t\t");
657
      // Выводим напряженность магнитного поля в Гауссах по оси Y
658
      Serial.print(compass1.readMagneticGaussY());
659
      Serial.print("\t\t");
660
      // Выводим напряженность магнитного поля в Гауссах по оси Z
661
      Serial.println(compass1.readMagneticGaussZ());
662
      Serial.println("=================================================");
663
    */

 

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

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

fedoroff_alexander
Offline
Зарегистрирован: 12.04.2015

ЕвгенийП пишет:

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

Это такой проект. Что то типа тестовый. Для развития. Нужно понимать, что существует много "компасов" различных производителей. К ним есть библиотеки-драйверы. И у всех своя реализация, единицы измерений, погрешности датчиков. Думаю, что этот проект Вы должны рассматривать как пример программной реализации с измерениями в Попугаях. А документацию к готовым проектам я стараюсь писать. Например вот в этом проекте. https://t.me/joinchat/SGc7NdkZFohmZDEy 

 

Upper
Offline
Зарегистрирован: 23.06.2020

Ну не знает большинство людей, что такое ДОМАШНИЙ МАГНИТОМЕТР. Я не знаю что такое и не домашний.

Скачал ваш архив, думал там будет написано для чего может быть использован. Какие возможны сценарии и с какой точностью.
Но не нашел.

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

fedoroff_alexander
Offline
Зарегистрирован: 12.04.2015

Upper пишет:

Ну не знает большинство людей, что такое ДОМАШНИЙ МАГНИТОМЕТР. Я не знаю что такое и не домашний.

Скачал ваш архив, думал там будет написано для чего может быть использован. Какие возможны сценарии и с какой точностью.
Но не нашел.

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

IMU-сенсор 10-DOF v2: инструкция, схемы и примеры использования [Амперка / Вики] (amperka.ru)

Насколько я понимаю правильно, сам плохо ориентируюсь в магнетизме земли. Специальный датчик, он же датчик магнитного компаса (могу не правильно излагать термины) измеряет напряженность магнитного поля, определить направление Севера, наклон датчика например относительно горизонта... Программа, это просто оболочка-врапер дающая возможность считать какое то значение датчика по осям Х, Y, Z. Удобно визуализировать в виде бегущих графиков на дисплее значения измерений. Отображает значения в виде цифр. Есть возможность переключать и отображать на дисплее оси координат. Переключать экраны для графиков датчиков. Есть меню и возможность устанавливать пороги срабатывания по MAX и MIN значений. Для того что бы не лезть в код. Есть программный блок, где можно писать свои обработчики полученных данных от датчиков. В программе он специально выделен комментариями. Где использовать? Ну например на пляже в песке забытые монеты и тому подобное на глубине не более 10 см :) Профессиональные комлексы с другими принципами, ищут подводные лодки на глубина в 100 метры. Характеристики ищут в специальных документах на датчики. Даташит.

sadman41
Offline
Зарегистрирован: 19.10.2016

Есть такая штука уже модулем... Работает без ардуины. Напрямую с Nextion, например: https://youtube.com/shorts/0nEAC3PHouc