Магнитометр

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

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

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

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

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

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

001/*
002   Домашний магнетометр
003   Модуль ESP32 WROOM. В менеджере плат - DOIT ESP32 DEVKIT V1. Версия для ESP32 - Espresiif system v 1.0.6
004   Arduino IDE 1.8.13
005*/
006#define SCREEN_WIDTH 128 // OLED display width, in pixels
007#define SCREEN_HEIGHT 64 // OLED display height, in pixels
008#define sizeTrend 30//количество точек в тренде
009#define OLED_MOSI   23
010#define OLED_CLK    18
011#define OLED_DC     16
012#define OLED_CS     5 //Для других SPI устойств CS должен быть другим
013#define OLED_RESET  17
014#define BUZZER_PIN 2
015#define BUZZER_CHANNEL 0
016 
017#include <Tone32.h>
018#include <SPI.h>
019#include <Wire.h>
020#include <Adafruit_GFX.h>
021#include <Adafruit_SSD1306.h>
022#include <Adafruit_Sensor.h>
023//#include <DFRobot_QMC5883.h>
024#include <Adafruit_LIS3MDL.h>
025#include "GyverTimer.h"
026 
027int Freq_signal = 100;
028GTimer myTimer(MS, Freq_signal);    // создать миллисекундный таймер
029//GTimer myTimer(US);    // US - микросекундный
030#include "GyverButton.h"
031// Варианты инициализации кнопок:
032// GButton btn;// без привязки к пину (виртуальная кнопка) и без указания типа (по умолч. HIGH_PULL и NORM_OPEN)
033// GButton btn(пин);// с привязкой к пину и без указания типа (по умолч. HIGH_PULL и NORM_OPEN)
034// GButton btn(пин, тип подключ.);// с привязкой к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и без указания типа кнопки (по умолч. NORM_OPEN)
035// GButton btn(пин, тип подключ., тип кнопки);// с привязкой к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и типа кнопки (NORM_OPEN / NORM_CLOSE)
036// GButton btn(BTN_NO_BTN_PIN, тип подключ., тип кнопки);// без привязки к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и типа кнопки (NORM_OPEN / NORM_CLOSE)
037 
038//DFRobot_QMC5883 compass1;
039//DFRobot_QMC5883 compass2;
040//Декларируем две I2C шины
041 
042/*int *in1 = new int[sizeTrend+1];  //массив для первого тренда
043  int *in2 = new int[sizeTrend+1];  //массив для второго тренда
044  int *in3 = new int[sizeTrend+1];  //массив для второго тренда*/
045int in1[sizeTrend]; //массив для первого тренда
046int in2[sizeTrend]; //массив для второго тренда
047int in3[sizeTrend]; //массив для второго тренда
048const int LED = 15; //синий светодиод
049//int r=0;
050int x, y, z, t; int _x, _y, _z, _t;
051int X1, Y1, Z1; int X2, Y2, Z2;
052int Min, Max; int MIN, MAX; int MIN2, MAX2;
053 
054int cnt_LeftRight = 1;      //Счетчик перемещения по горизонтальному меню
055int cnt_UpDown = 1;         //Счетчик перемещения по вертикальному меню
056int cnt_UpDownSensor = 1;   //Счетчик перемещения по вертикальному меню для сенсоров
057bool flag_UpDownSensor = true;
058 
059Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
060                         OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
061GButton btn_Left(27);
062GButton btn_Right(12);
063GButton btn_Up(13);
064GButton btn_Down(14);
065GButton btn_Enter(26);
066Adafruit_LIS3MDL compass1;
067Adafruit_LIS3MDL compass2;
068 
069bool menu_OnOff = false; bool menu_Senor = true;
070char *Coordinats = "ZXY"; int cnt_Coordinats = 1;
071int TrigerMINz = 0; int TrigerMAXz = 0;
072int MINz = 400; int MAXz = -400;
073int Volume = 0; int freq = 600; int channel = 0;
074int resolution = 8;
075int Buzzer = 0; int Algoritm = 1; int Chanel = 1;
076int Raznica = 0; int Porog = 0; int Param1 = 0; float Param2 = 0.0;
077 
078//конвертирование данных из массива для варианта приема байтовых значений
079int convert(int y, int mn, int mx, byte yTrend, byte heightTrend, int *buf ) {
080  int ny = y;
081  ny = map(ny, mn, mx, heightTrend - 1 + yTrend, yTrend);
082  //ny=map(ny,mn,mx,yTrend,heightTrend-1+yTrend);
083  return ny;
084}
085 
086//отрисовка тренда (ширина, высота, x координата, y координата, аналоговый вход, массив для хранения измерений)
087void drawTrend(int widthTrend, int heightTrend, int xTrend, int yTrend, int cn, int *buf) {
088  buf[sizeTrend - 1] = cn; //добавляем новое значение
089  int oldX = 0;
090  int oldY = 0 + yTrend;
091  int mn = MINz; //для поиска минимума
092  int mx = MAXz; //для поиска максимума
093  double k = 0.0;
094  //сдвигаем график
095  for  (int x = 0; x < (sizeTrend - 1); x++) {
096    buf[x] = buf[x + 1]; //переписываем в текущюю ячейку массива данные из следующей
097  }
098 
099  //поиск мин и макс
100  for (int i = 0; i < sizeTrend; i++) { //пробегаем по массиву
101    if (buf[i] > mx) { //если значение в ячейке больше макс
102      mx = buf[i]; //то макс = содержимому ячейки
103    }
104    if (buf[i] < mn) { //если значение в ячейке меньше мин
105      mn = buf[i]; //то мин = содержимому ячейки
106    }
107  }
108  if (mn == mx) { //если мин=макс
109    mx = mn + 1; //устанавливаем макс+=1
110    mn = mn - 1; //мин-=1
111  }
112 
113  //формирование буфера вывода
114  for (int x = 0; x < sizeTrend - 1; x++) { //Х координата
115    int y = convert(buf[x], mn, mx, yTrend, heightTrend, buf); //Y координата
116    int nxt_x = map(x, 0, sizeTrend - 1, 0, widthTrend);
117    //отрисовка тренда
118    display.drawLine(xTrend + oldX, oldY, xTrend + nxt_x, y, WHITE);
119    oldX = nxt_x;
120    oldY = y;
121  }
122   
123  //отрисовка рамки
124  display.drawRect(xTrend, yTrend, widthTrend, heightTrend, WHITE);
125 
126  //вывод минимума и максимума на экран
127  display.setCursor(xTrend + widthTrend + 3, yTrend);
128  display.println(mx); Max = mx;
129  display.setCursor(xTrend + widthTrend + 3, yTrend + heightTrend - 8);
130  display.println(mn); Min = mn;
131  display.setCursor(xTrend + widthTrend + 3, yTrend + (heightTrend / 2) - 4);
132  display.println(buf[sizeTrend - 1]); //текущее
133  oldX = 0; //чтобы новая линия сначала тренда отрисовывалась
134  oldY = convert(buf[0], mn, mx, yTrend, heightTrend, buf);
135 
136}
137 
138//Опрашиваем кнопки по прерыванию*************************************************************************
139void isr_Left() {
140  btn_Left.tick();
141}
142void isr_Right() {
143  btn_Right.tick();
144}
145void isr__Up() {
146  btn_Up.tick();
147}
148void isr__Down() {
149  btn_Down.tick();
150}
151void isr__Enter() {
152  btn_Enter.tick();
153}
154//********************************************************************************************************
155 
156void setup() {
157  Serial.begin(115200);
158  //memset(in1, 0x0, sizeTrend);
159  //memset(in2, 0x0, sizeTrend);
160  //memset(in3, 0x0, sizeTrend);
161  pinMode(LED, OUTPUT); //синий светодиод тревоги
162  digitalWrite(LED, LOW);
163  pinMode(19, OUTPUT); //красный светодиод тревоги
164  digitalWrite(19, LOW);
165 
166  //Настройка кнопок**************************************************************************************
167  // настройка антидребезга (по умолчанию 80 мс)
168  // настройка таймаута на удержание (по умолчанию 500 мс)
169  btn_Left.setDebounce(50); btn_Left.setTimeout(300);
170  btn_Right.setDebounce(50); btn_Right.setTimeout(300);
171  btn_Up.setDebounce(50); btn_Up.setTimeout(300);
172  btn_Down.setDebounce(50); btn_Down.setTimeout(300);
173  btn_Enter.setDebounce(50); btn_Enter.setTimeout(300);
174  //Кнопки настроены***************************************************************************************
175 
176  //Init display ******************************************************************************************
177  if (!display.begin(SSD1306_SWITCHCAPVCC)) {
178    Serial.println(F("SSD1306 allocation failed"));
179  }
180  display.display();
181  delay(1000);
182  display.clearDisplay();
183  display.setCursor(0, 0);
184  display.setTextSize(1);
185  display.setTextColor(SSD1306_WHITE);  // Draw white text
186  display.cp437(true);                  // Use full 256 char 'Code Page 437' font
187  display.println("Init...");
188  display.println("Display SSD1306");
189  //End Init display ****************************************************************************************
190 
191  // Initialize magnetic sensors  LIS3MDL********************************************************************
192  if (compass1.begin_I2C(0x1E)) {          // hardware I2C mode, can pass in address & alt Wire 0x1E
193    display.println("Sensor1 Ok");
194  }
195  if (compass2.begin_I2C(0x1C)) {          // hardware I2C mode, can pass in address & alt Wire0x1C
196    display.println("Sensor2 Ok");
197  }
198  // End initialize  LIS3MDL*********************************************************************************
199 
200  // Initialize magnetic sensors HMC5883, QMC5883, VCM5883L**************************************************
201  /*while (!compass1.begin()) {
202    //Serial.println("Could not find a valid magnetic sensor, check wiring!");
203    display.println("No magnetic sensor1");
204    delay(500);
205    }
206 
207    if (compass1.isHMC()) {
208    //Serial.println("Sensor1 HMC5883");
209    display.println("Sensor1 HMC5883");
210    //compass1.setRange(HMC5883L_RANGE_1_3GA);
211    //compass1.setMeasurementMode(HMC5883L_CONTINOUS);
212    //compass1.setDataRate(HMC5883L_DATARATE_15HZ);
213    //compass1.setSamples(HMC5883L_SAMPLES_8);
214    } else if (compass1.isQMC()) {
215    //Serial.println("Sensor1 QMC5883");
216    display.println("Sensor1 QMC5883");
217    compass1.setRange(QMC5883_RANGE_2GA);
218    //compass1.setMeasurementMode(QMC5883_CONTINOUS);
219    //compass1.setDataRate(QMC5883_DATARATE_50HZ);
220    //compass1.setSamples(QMC5883_SAMPLES_8);
221    } else if (compass1.isVCM()) {
222    //Serial.println("Sensor1 VCM5883L");
223    display.println("Sensor1 VCM5883L");
224    //compass1.setMeasurementMode(VCM5883L_CONTINOUS);
225    //compass1.setDataRate(VCM5883L_DATARATE_200HZ);
226    } else display.println("No sensors1");
227 
228    while (!compass2.begin()){
229    //Serial.println("Could not find a valid magnetic sensor, check wiring!");
230    display.println("No magnetic sensor1");
231    delay(500);
232    }
233    if (compass2.isHMC()){
234    //Serial.println("Sensor2 HMC5883");
235    display.println("Sensor2 HMC5883");
236    //compass2.setRange(HMC5883L_RANGE_1_3GA);
237    //compass2.setMeasurementMode(HMC5883L_CONTINOUS);
238    //compass2.setDataRate(HMC5883L_DATARATE_15HZ);
239    //compass2.setSamples(HMC5883L_SAMPLES_8);
240    }else if (compass2.isQMC()){
241    //Serial.println("Sensor2 QMC5883");
242    display.println("Sensor2 QMC5883");
243    compass2.setRange(QMC5883_RANGE_2GA);
244    //compass2.setMeasurementMode(QMC5883_CONTINOUS);
245    //compass2.setDataRate(QMC5883_DATARATE_50HZ);
246    //compass2.setSamples(QMC5883_SAMPLES_8);
247    }else if (compass2.isVCM()){
248    //Serial.println("Sensor VCM5883L");
249    display.println("Sensor2 VCM5883L");
250    //compass2.setMeasurementMode(VCM5883L_CONTINOUS);
251    //compass2.setDataRate(VCM5883L_DATARATE_200HZ);
252    } else display.println("No sensors2");*/
253  // End initialize HMC5883, QMC5883, VCM5883L *************************************************
254 
255  display.display();
256  delay(4000);
257  display.clearDisplay();
258  display.setCursor(0, 0);
259  display.setTextSize(1);
260  display.setTextColor(SSD1306_WHITE);  // Draw white text
261  display.cp437(true);                  // Use full 256 char 'Code Page 437' font
262 
263  //Вывести Номер сенсора-датчика
264  for (int cntr = 1; cntr < 9; cntr++) {
265    display.clearDisplay();             //Очистить буфер дисплея и картинку
266    display.setCursor(0, 0);  display.setTextSize(cntr); display.print(cnt_UpDownSensor);
267    display.display();
268    delay(100);
269  }
270  display.setTextSize(1);
271  display.clearDisplay();
272  display.display();
273 
274  //Инициализация зумера тревоги
275  ledcSetup(channel, freq, resolution);
276  ledcAttachPin(2, channel);
277}
278 
279void loop() {
280  btn_Left.tick();  // опрашиваем в скетче, иначе не будут работать проверки по времени!
281  btn_Right.tick();
282  btn_Up.tick();
283  btn_Down.tick();
284  btn_Enter.tick();
285  //Раскоментировать для тестирования кнопок*****************************************************
286  /*if (btn_Left.isSingle()) Serial.println("Single Left");     // проверка на один клик
287    if (btn_Left.hasClicks())                                   // проверка на наличие нажатий
288    Serial.println(btn_Left.getClicks());                       // получить (и вывести) число нажатий
289    if (btn_Right.isSingle()) Serial.println("Single Right");   // проверка на один клик
290    if (btn_Right.hasClicks())                                  // проверка на наличие нажатий
291    Serial.println(btn_Right.getClicks());                      // получить (и вывести) число нажатий*/
292  //***********************************************************************************************
293 
294  if (myTimer.isReady()) {
295    display.clearDisplay(); //Очистить буфер дисплея и картинку
296     
297    //МЕНЮ On/Off***************************************************************************************
298    if (btn_Enter.hasClicks()) {
299      menu_OnOff = !menu_OnOff;
300      menu_Senor = !menu_OnOff;
301    }
302    //МЕНЮ On/Off end***********************************************************************************
303 
304    //Установка порядка и размеров графиков по координатом на экране************************************
305 
306    //Клавиша ВЛЕВО*************************************************************************************
307    if (btn_Left.hasClicks() && menu_OnOff) {
308      --cnt_LeftRight;
309      int clicks = btn_Left.getClicks(); //число кликов
310      if (clicks != 1) cnt_LeftRight = clicks;
311    }
312    //Отработано Клавиша ВЛЕВО**************************************************************************
313 
314    //Клавиша ВПРАВО************************************************************************************
315    if (btn_Right.hasClicks() && menu_OnOff) {
316      ++cnt_LeftRight;
317      //--cnt_UpDownSensor;
318      int clicks = btn_Right.getClicks(); //число кликов
319      if (clicks != 1) cnt_LeftRight = clicks;
320    }
321    //Отработано Клавиша ВПРАВО*************************************************************************
322 
323    //Клавиша ВВЕРХ, cnt_UpDown = количеству пунктов вертикального меню*********************************
324    if (btn_Up.hasClicks() && menu_OnOff) {
325      --cnt_UpDown;
326      int clicks = btn_Up.getClicks(); //число кликов
327      if (clicks != 1) cnt_UpDown = clicks;
328    }
329    //end ВВЕРХ******************************************************************************************
330 
331    //Клавиша ВНИЗ***************************************************************************************
332    if (btn_Down.hasClicks() && menu_OnOff) {
333      ++cnt_UpDown;
334      int clicks = btn_Down.getClicks(); //число кликов
335      if (clicks != 1) cnt_UpDown = clicks;
336    }
337    //end Клавиша ВНИЗ************************************************************************************
338 
339    //Обрабатываем ВВЕРХ-ВНИЗ*****************************************************************************
340 
341    //Показать номер сенсора******************************************************************************
342    if (!menu_OnOff) {
343      if (btn_Up.hasClicks() && !menu_OnOff) {
344        --cnt_UpDownSensor;
345        flag_UpDownSensor = !flag_UpDownSensor;
346        if (cnt_UpDownSensor < 1) cnt_UpDownSensor = 2;
347        for (int cntr = 1; cntr < 9; cntr++) {
348          display.clearDisplay(); //Очистить буфер дисплея и картинку
349          display.setCursor(0, 0);  display.setTextSize(cntr); display.print(cnt_UpDownSensor);
350          display.display();
351          delay(50);
352        }
353        display.setTextSize(1);
354        display.clearDisplay();
355        display.display();
356      }
357 
358      if (btn_Down.hasClicks() && !menu_OnOff) {
359        ++cnt_UpDownSensor;
360        flag_UpDownSensor = !flag_UpDownSensor;
361        if (cnt_UpDownSensor > 2) cnt_UpDownSensor = 1;
362        for (int cntr = 1; cntr < 9; cntr++) {
363          display.clearDisplay(); //Очистить буфер дисплея и картинку
364          display.setCursor(0, 0);  display.setTextSize(cntr); display.print(cnt_UpDownSensor);
365          display.display();
366          delay(50);
367        }
368        display.setTextSize(1);
369        display.clearDisplay();
370        display.display();
371      }
372    }
373    //Показали номер сенсора******************************************************************************
374 
375    //Меню************************************************************************************************
376    if (menu_OnOff) {
377      if (cnt_UpDown < 1) cnt_UpDown = 6;
378      if (cnt_UpDown > 6) cnt_UpDown = 1;
379      switch (cnt_UpDown) {
380        case 1:
381          if (btn_Right.hasClicks()) cnt_Coordinats += 1;
382          if (cnt_Coordinats > 3) cnt_Coordinats = 1;
383          if (btn_Left.hasClicks()) cnt_Coordinats -= 1;
384          if (cnt_Coordinats < 1) cnt_Coordinats = 3;
385          if (cnt_Coordinats == 1) {
386            Coordinats = "";
387            Coordinats = "ZXY";
388          }
389          if (cnt_Coordinats == 2) {
390            Coordinats = "";
391            Coordinats = "YZX";
392          }
393          if (cnt_Coordinats == 3) {
394            Coordinats = "";
395            Coordinats = "XYZ";
396          }
397          //display.clearDisplay();
398          display.setCursor(5, 0);  display.printf("> %-12s  %s", "Coordinats", Coordinats);
399          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
400          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
401          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
402          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
403          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
404          display.display();
405          break;
406        case 2:
407          if (btn_Right.hasClicks()) {
408            int clicks = btn_Right.getClicks(); //число кликов
409            if (clicks == 1) ++TrigerMAXz;
410            if (clicks == 2) TrigerMAXz += 10;
411            if (clicks == 3) TrigerMAXz += 100;
412            if (clicks == 4) TrigerMAXz += 1000;
413          }
414          if (btn_Left.hasClicks()) {
415            int clicks = btn_Left.getClicks(); //число кликов
416            if (clicks == 1) --TrigerMAXz;
417            if (clicks == 2) TrigerMAXz -= 10;
418            if (clicks == 3) TrigerMAXz -= 100;
419            if (clicks == 4) TrigerMAXz -= 1000;
420          }
421          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
422          display.setCursor(5, 10); display.printf("> %-12s  %d", "Triger MAXz", TrigerMAXz);
423          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
424          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
425          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
426          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
427          display.display();
428          break;
429        case 3:
430          if (btn_Right.hasClicks()) {
431            int clicks = btn_Right.getClicks(); //число кликов
432            if (clicks == 1) ++TrigerMINz;
433            if (clicks == 2) TrigerMINz += 10;
434            if (clicks == 3) TrigerMINz += 100;
435            if (clicks == 4) TrigerMINz += 1000;
436          }
437          if (btn_Left.hasClicks()) {
438            int clicks = btn_Left.getClicks(); //число кликов
439            if (clicks == 1) --TrigerMINz;
440            if (clicks == 2) TrigerMINz -= 10;
441            if (clicks == 3) TrigerMINz -= 100;
442            if (clicks == 4) TrigerMINz -= 1000;
443          }
444          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
445          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
446          display.setCursor(5, 20); display.printf("> %-12s  %d", "Triger MINz", TrigerMINz);
447          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
448          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
449          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
450          display.display();
451          break;
452        case 4:
453          if (btn_Right.hasClicks()) {
454            int clicks = btn_Right.getClicks(); //число кликов
455            if (++Buzzer > 1) Buzzer = 0;
456          }
457          if (btn_Left.hasClicks()) {
458            int clicks = btn_Left.getClicks(); //число кликов
459            if (--Buzzer < 0) Buzzer = 1;
460          }
461          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
462          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
463          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
464          display.setCursor(5, 30); display.printf("> %-12s  %d", "Buzzer", Buzzer);
465          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
466          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
467          display.display();
468          break;
469        case 5:
470          if (btn_Right.hasClicks()) {
471            int clicks = btn_Right.getClicks(); //число кликов
472            if (++Algoritm > 2) Algoritm = 1;
473          }
474          if (btn_Left.hasClicks()) {
475            if (--Algoritm < 1) Algoritm = 2;
476          }
477          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
478          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
479          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
480          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
481          display.setCursor(5, 40); display.printf("> %-12s  %d", "Algoritm", Algoritm);
482          display.setCursor(5, 50); display.printf("6 %-12s  %d", "Sensor", cnt_UpDownSensor);
483          display.display();
484          break;
485        case 6:
486          if (btn_Right.hasClicks()) {
487            int clicks = btn_Right.getClicks(); //число кликов
488            if (++cnt_UpDownSensor > 2) cnt_UpDownSensor = 1;
489          }
490          if (btn_Left.hasClicks()) {
491            int clicks = btn_Left.getClicks(); //число кликов
492            if (--cnt_UpDownSensor < 1) cnt_UpDownSensor = 2;
493          }
494          display.setCursor(5, 0);  display.printf("1 %-12s  %s", "Coordinats", Coordinats);
495          display.setCursor(5, 10); display.printf("2 %-12s  %d", "Triger MAXz", TrigerMAXz);
496          display.setCursor(5, 20); display.printf("3 %-12s  %d", "Triger MINz", TrigerMINz);
497          display.setCursor(5, 30); display.printf("4 %-12s  %d", "Buzzer", Buzzer);
498          display.setCursor(5, 40); display.printf("5 %-12s  %d", "Algoritm", Algoritm);
499          display.setCursor(5, 50); display.printf("> %-12s  %d", "Sensor", cnt_UpDownSensor);
500          display.display();
501          break;
502      }
503    }
504    //end ВВЕРХ-ВНИЗ Меню*********************************************************************************
505 
506    //Обрабатываем ВЛЕВО-ВПРАВО***************************************************************************
507    if (!menu_OnOff) {
508      if (btn_Right.hasClicks()) cnt_Coordinats += 1;
509      if (cnt_Coordinats > 3) cnt_Coordinats = 1;
510      if (btn_Left.hasClicks()) cnt_Coordinats -= 1;
511      if (cnt_Coordinats < 1) cnt_Coordinats = 3;
512      if (cnt_UpDownSensor == 1) { //Работаем с 1 сенсором
513        _x = X1; _y = Y1; _z = Z1;
514      }
515      if (cnt_UpDownSensor == 2) { //Работаем с 2 сенсором
516        _x = X2; _y = Y2; _z = Z2;
517      }
518      switch (cnt_Coordinats) {
519        case 1:
520          Coordinats = ""; Coordinats = "ZXY";
521          display.setCursor(0, 25); display.println("z");
522          display.setCursor(25, 30); display.println("x");
523          display.setCursor(90, 30); display.println("y");
524          //int Raznica = 0; int Porog = 0; int Param1 = 0; float Param2 = 0.0;
525          if (Algoritm == 2) {
526            display.setCursor(10, 25);
527            display.printf("[%d] [%d] [%.1f]", Raznica,Porog,Param2);
528          }
529          drawTrend(95, 25, 0, 0, _z, in1); //вывод 1 тренда по данным из массива in1-Z
530          //Запись в переменные в зависимости от выбранного канала датчика cnt_UpDownSensor по Z**********
531          if (cnt_UpDownSensor == 1) {
532            MIN = Min; MAX = Max;
533          }
534          if (cnt_UpDownSensor == 2) {
535            MIN2 = Min; MAX2 = Max;
536          }
537          //***********************************************************************************************
538          drawTrend(30, 25, 0, 39, _x, in2); //вывод второго по данным из in2-X
539          drawTrend(34, 25, 60, 39, _y, in3); //вывод третьего по данным из in3-Y
540          display.display();
541          break;
542        case 2:
543          Coordinats = ""; Coordinats = "YZX";
544          //display.clearDisplay();
545          display.setCursor(0, 25); display.println("y");
546          display.setCursor(25, 30); display.println("z");
547          display.setCursor(90, 30); display.println("x");
548          if (Algoritm == 2) {
549            display.setCursor(10, 25);
550            display.printf("[%d] [%d] [%.1f]", Raznica,Porog,Param2);
551          }
552          drawTrend(95, 25, 0, 0, _y, in3); //вывод 1 тренда по данным из массива in3-Y
553          drawTrend(30, 25, 0, 39, _z, in1); //вывод второго по данным из in1-Z
554          //Запись в переменные в зависимости от выбранного канала датчика cnt_UpDownSensor по Z************
555          //MIN2 = Min; MAX2 = Max; X2 = x; Y2 = y; Z2 = z;
556          if (cnt_UpDownSensor == 1) {
557            MIN = Min; MAX = Max;
558          }
559          if (cnt_UpDownSensor == 2) {
560            MIN2 = Min; MAX2 = Max;
561          }
562          //*************************************************************************************************
563          drawTrend(34, 25, 60, 39, _x, in2); //вывод третьего по данным из in2-X
564          display.display();
565          break;
566        case 3:
567          Coordinats = ""; Coordinats = "XYZ";
568          //display.clearDisplay();
569          display.setCursor(0, 25); display.println("x");
570          display.setCursor(25, 30); display.println("y");
571          display.setCursor(90, 30); display.println("z");
572          if (Algoritm == 2) {
573            display.setCursor(10, 25);
574            display.printf("[%d] [%d] [%.1f]", Raznica,Porog,Param2);
575          }
576          drawTrend(95, 25, 0, 0, _x, in2); //вывод 1 тренда по данным из массива in2-X
577          drawTrend(30, 25, 0, 39, _y, in3); //вывод второго по данным из in3-Y
578          drawTrend(34, 25, 60, 39, _z, in1); //вывод третьего по данным из in1-Z
579          if (cnt_UpDownSensor == 1) {
580            MIN = Min; MAX = Max;
581          }
582          if (cnt_UpDownSensor == 2) {
583            MIN2 = Min; MAX2 = Max;
584          }
585          display.display();
586          break;
587 
588      }
589    }
590    display.clearDisplay(); //Очистить буфер дисплея и картинку
591    //display.display();
592    //Отработали ВЛЕВО-ВПРАВО*****************************************************************************
593 
594    //выводим в плоттер по последовательному порту в зависимости от выбранного датчика*******
595    //После отладки закоментировать блок
596    if (cnt_UpDownSensor == 1) {
597      Serial.print(" X1:");
598      Serial.print(X1);
599      Serial.print(" Y1:");
600      Serial.print(Y1);
601      Serial.print(" Z1:");
602      Serial.println(Z1);
603    }
604    if (cnt_UpDownSensor == 2) {
605      Serial.print(" X2:");
606      Serial.print(X2);
607      Serial.print(" Y2:");
608      Serial.print(Y2);
609      Serial.print(" Z2:");
610      Serial.println(Z2);
611    }
612 
613    //плоттер end****************************************************************************************
614    myTimer.start(); //Перезапуск таймера
615  }
616   
617  /*if (cnt_UpDownSensor == 1) {    //Первый I2C датчик QMC5883
618      Vector mag = compass1.readRaw();// Читаем значения датчика. При другой библиотеке и датчике заменить
619      //x = mag.XAxis;
620      //y = mag.YAxis;
621      //z = mag.ZAxis;
622      X1 = mag.XAxis;
623      Y1 = mag.YAxis;
624      Z1 = mag.ZAxis;
625      }
626      if (cnt_UpDownSensor == 2) {    //Второй I2C датчик QMC5883
627      Vector mag = compass1.readRaw();// Читаем значения датчика. При другой библиотеке и датчике заменить
628      X2 = mag.XAxis;
629      Y2 = mag.YAxis;
630      Z2 = mag.ZAxis;
631      }*/
632    sensors_event_t event1;
633    sensors_event_t event2;
634    //if (cnt_UpDownSensor == 1) {    //Первый I2C датчик
635    /*compass1.read(); //в Гаусах
636      X1 = compass1.x;
637      Y1 = compass1.y;
638      Z1 = compass1.z;*/
639    compass1.getEvent(&event1); //в Тесла
640    X1 = event1.magnetic.x;
641    Y1 = event1.magnetic.y;
642    Z1 = event1.magnetic.z;
643    //}
644    //if (cnt_UpDownSensor == 2) {    //Второй I2C датчик
645    /*compass2.read(); //в Гаусах
646      X2 = compass2.x;
647      Y2 = compass2.y;
648      Z2 = compass2.z;*/
649    compass2.getEvent(&event2); //в Тесла
650    X2 = event2.magnetic.x;
651    Y2 = event2.magnetic.y;
652    Z2 = event2.magnetic.z;
653    //}
654    /*Тест для датчика Амперка
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    */
664   
665  //*****************************************************************************************************
666  //*****************************************************************************************************
667  //*****************************************************************************************************
668  /*
669       БЛОК МОЙ КОД
670       ЦИКЛЫ ДЕЛАТЬ НЕЛЬЗЯ (крайне не рекомендуется)!!!. СОБЪЕТСЯ ЧАСТОТА ОПРОСА СИГНАЛА и скорость вывода на экран.
671       Чем больше интервал частоты опроса (реже опрашиваем), тем больше мы срезаем ПОМЕХ.
672       (int) Freq_signal = 100 милисекунд. Можете изменить частоту опроса датчиков
673       Здесь пишем алгоритмы обработки сигнала...
674       Когда и при каких условиях срабатывают тригеры...
675       Когда и как срабатывает световая и звуковая сигнализация...
676       (int) TrigerMINz - устанавливается в Меню вручную. Граница срабатывания по оси Z
677       (int) TrigerMAXz - устанавливается в Меню вручную. Граница срабатывания по оси Z
678       Данные с выбранного в Меню датчика реализовано только по оси Z
679       Значение cnt_UpDownSensor == 1 - Первый I2C датчик
680       Значение cnt_UpDownSensor == 2 - Второй I2C датчик
681       В зависимости от cnt_UpDownSensor в x, y, z будут отражены данные от 1го или 2го датчика
682       (int) x - значение 1(2) датчика по X
683       (int) y - значение 1(2) датчика по Y
684       (int) z - значение 1(2) датчика по Z
685       (int) X1, Y1, Z1 - переменные для экспериментов по первому датчику
686       (int) X2, Y2, Z2 - переменные для экспериментов по второму датчику
687       (int) MIN, MAX - переменные для экспериментов по первому датчику установленные программно
688       (int) MIN2, MAX2 - переменные для экспериментов по второму датчику установленные программно
689       (int) Algoritm - переключатель алгоритма обработки значений датчика
690       (int) LED - Адрес светодиода 15 (D15)
691       (int) BUZZER_PIN - Адрес зумера 2 (D2)
692 
693       (int) Raznica = 0; (int) Porog = 0; (int) Param1 = 0; (float) Param2 = 0.0;
694       Алгоритм работы с двумя датчиками
695 
696        Dat1 - показания первого датчика после усреднения.
697        Dat2 - показания второго датчика после усреднения.
698        Porog - порог срабатывания (настраивается кнопками на плате).
699        Raznica - разница между показаниями двух датчиков.
700 
701        Прибор срабатывает (подает звуковой сигнал) если Raznica по модулю (без учета знака +-) >= Porog.
702        if (abs(Dat1 - Dat2) >= Porog) { даем сигнал на динамик }
703 
704        Усреднение данных - Экспоненциальное бегущее среднее
705 
706        float k = 0.1; // коэффициент фильтрации, 0.0-1.0
707        // бегущее среднее
708        float expRunningAverage(float newVal) {
709            static float filVal = 0;
710            filVal += (newVal - filVal) * k;
711            return filVal;
712        }
713        "Сила" фильтра настраивается коэффициентом (0.0 – 1.0). Чем он меньше, тем плавнее фильтр
714 
715       В ДРУГОЙ КОД НЕ ЛЕЗЕМ!!! Внутри БЛОКА все что угодно. Делаем копию БЛОКА!
716  */
717  //Отладка. Выводим в монитор последовательного порта. Мешает выводу в плоттер. После отладки закоментировать***
718  //Serial.printf("X1    = %6d, Y1    = %6d, Z1  = %6d\n",X1, Y1, Z1);
719  //Serial.printf("X2   = %6d, Y2   = %6d, Z2 = %6d\n",X2, Y2, Z2);
720  //Serial.printf("MIN  = %6d, MAX  = %6d\n", MIN, MAX);
721  //Serial.printf("MIN2 = %6d, MAX2 = %6d\n", MIN2, MAX2);
722  //Монитор end***************************************************************************************************
723 
724  //Алгоритм 1. Обрабатывает данные минимального и максимального значения датчика по оси Z
725  //включает/выключает синий светодиод (минимум), краный светодиод (максимум) и зуммер
726  if (Algoritm == 1) {
727    if (Z1 < TrigerMINz) {
728      digitalWrite(LED, HIGH);
729      if (Buzzer == 1) {
730        //tone(BUZZER_PIN, NOTE_C4, 5, BUZZER_CHANNEL);
731        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
732        //tone(BUZZER_PIN, NOTE_D4, 500, BUZZER_CHANNEL);
733        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
734        //tone(BUZZER_PIN, NOTE_E4, 500, BUZZER_CHANNEL);
735        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
736        //tone(BUZZER_PIN, NOTE_F4, 500, BUZZER_CHANNEL);
737        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
738        //tone(BUZZER_PIN, NOTE_G4, 500, BUZZER_CHANNEL);
739        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
740        //tone(BUZZER_PIN, NOTE_A4, 500, BUZZER_CHANNEL);
741        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
742        tone(BUZZER_PIN, NOTE_B4, 10, BUZZER_CHANNEL);
743        noTone(BUZZER_PIN, BUZZER_CHANNEL);
744      }
745      else noTone(BUZZER_PIN, BUZZER_CHANNEL);
746    }
747    else digitalWrite(LED, LOW);
748 
749    if (Z1 > TrigerMAXz) {
750      digitalWrite(19, HIGH);
751      if (Buzzer == 1) {
752        tone(BUZZER_PIN, NOTE_C4, 10, BUZZER_CHANNEL);
753        noTone(BUZZER_PIN, BUZZER_CHANNEL);
754        //tone(BUZZER_PIN, NOTE_D4, 500, BUZZER_CHANNEL);
755        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
756        //tone(BUZZER_PIN, NOTE_E4, 500, BUZZER_CHANNEL);
757        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
758        //tone(BUZZER_PIN, NOTE_F4, 500, BUZZER_CHANNEL);
759        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
760        //tone(BUZZER_PIN, NOTE_G4, 500, BUZZER_CHANNEL);
761        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
762        //tone(BUZZER_PIN, NOTE_A4, 500, BUZZER_CHANNEL);
763        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
764        //tone(BUZZER_PIN, NOTE_B4, 5, BUZZER_CHANNEL);
765        //noTone(BUZZER_PIN, BUZZER_CHANNEL);
766      }
767      else noTone(BUZZER_PIN, BUZZER_CHANNEL);
768    }
769    else digitalWrite(19, LOW);
770  }
771 
772  //Алгоритм 2. Здесь исходный код Заказчика. Основаный на примере Алгоритм 1.
773  //включает/выключает ... if (abs(Dat1 - Dat2) >= Porog) { даем сигнал на динамик }
774    if (Algoritm == 2) {
775    Raznica = 1; Porog = 2; Param1 = 3; Param2 = 4.0;
776    if (Porog > TrigerMAXz) {
777      digitalWrite(19, HIGH);
778    }
779    else digitalWrite(19, LOW);
780    if (Porog > TrigerMAXz) {
781      digitalWrite(LED, HIGH);
782    }
783    else digitalWrite(19, LOW);
784  }
785 
786  /*
787     Конец блока МОЙ КОД********************************************************************************
788     В ДРУГОЙ КОД ВНЕ БЛОКА НЕ ЛЕЗЕМ!!!
789  */
790  //*****************************************************************************************************
791  //*****************************************************************************************************
792  //*****************************************************************************************************
793}//Конец цикла Loop

 

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

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

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

fedoroff_alexander
Offline
Зарегистрирован: 12.04.2015
01     //if (cnt_UpDownSensor == 1) {    //Первый I2C датчик
02635
03    /*compass1.read(); //в Гаусах
04 
05    compass1.getEvent(&event1); //в Тесла
06 
07    //if (cnt_UpDownSensor == 2) {    //Второй I2C датчик
08645
09    /*compass2.read(); //в Гаусах
10 
11    compass2.getEvent(&event2); //в Тесла
12 
13    /*Тест для датчика Амперка
14655
15       Serial.print(compass1.readMagneticGaussX());
16656
17      Serial.print("\t\t");
18657
19      // Выводим напряженность магнитного поля в Гауссах по оси Y
20658
21      Serial.print(compass1.readMagneticGaussY());
22659
23      Serial.print("\t\t");
24660
25      // Выводим напряженность магнитного поля в Гауссах по оси Z
26661
27      Serial.println(compass1.readMagneticGaussZ());
28662
29      Serial.println("=================================================");
30663
31    */

 

ЕвгенийП
ЕвгенийП аватар
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