Гироскоп и светодиод

Тема в разделе "Arduino & Shields", создана пользователем KatanaDie, 9 апр 2019.

  1. KatanaDie

    KatanaDie Нуб

    Здравствуйте, уважаемые! Помогите мне, пожалуйста.
    Вот программа для гироскопа, взятая с этого сайта https://arduinoplus.ru/podkluchaem-akselerometr-k-arduino/
    Код отлично работает, но мне нужно сделать так, чтобы когда X и Y в мониторинге порта были равны 150 начинал светиться светодиод. Нет необходимого опыта работы с ардуино, не могу найти нужную переменную и написать правильную программу, поэтому обращаюсь к вам.
    Ниже код программы.
    Код (C++):
    #include <Wire.h>
    #include "Kalman.h"
    Kalman kalmanX;
    Kalman kalmanY;
    uint8_t IMUAddress = 0x68;
    /* IMU Data */
    int16_t accX;
    int16_t accY;
    int16_t accZ;
    int16_t tempRaw;
    int16_t gyroX;
    int16_t gyroY;
    int16_t gyroZ;
    double accXangle; // Angle calculate using the accelerometer
    double accYangle;
    double temp;
    double gyroXangle = 180; // Angle calculate using the gyro
    double gyroYangle = 180;
    double compAngleX = 180; // Calculate the angle using a Kalman filter
    double compAngleY = 180;
    double kalAngleX; // Calculate the angle using a Kalman filter
    double kalAngleY;
    uint32_t timer;
    void setup() {
      Wire.begin();
      Serial.begin(9600);
      i2cWrite(0x6B,0x00); // Disable sleep mode    
      kalmanX.setAngle(180); // Set starting angle
      kalmanY.setAngle(180);
      timer = micros();
    }
    void loop() {
      /* Update all the values */
      uint8_t* data = i2cRead(0x3B,14);
      accX = ((data[0] << 8) | data[1]);
      accY = ((data[2] << 8) | data[3]);
      accZ = ((data[4] << 8) | data[5]);
      tempRaw = ((data[6] << 8) | data[7]);
      gyroX = ((data[8] << 8) | data[9]);
      gyroY = ((data[10] << 8) | data[11]);
      gyroZ = ((data[12] << 8) | data[13]);
      /* Calculate the angls based on the different sensors and algorithm */
      accYangle = (atan2(accX,accZ)+PI)*RAD_TO_DEG;
      accXangle = (atan2(accY,accZ)+PI)*RAD_TO_DEG;
      double gyroXrate = (double)gyroX/131.0;
      double gyroYrate = -((double)gyroY/131.0);
      gyroXangle += kalmanX.getRate()*((double)(micros()-timer)/1000000); // Calculate gyro angle using the unbiased rate
      gyroYangle += kalmanY.getRate()*((double)(micros()-timer)/1000000);
      kalAngleX = kalmanX.getAngle(accXangle, gyroXrate, (double)(micros()-timer)/1000000); // Calculate the angle using a Kalman filter
      kalAngleY = kalmanY.getAngle(accYangle, gyroYrate, (double)(micros()-timer)/1000000);
      timer = micros();
    Serial.println();
        Serial.print("X:");
        Serial.print(kalAngleX,0);
        Serial.print(" ");
        Serial.print("Y:");
        Serial.print(kalAngleY,0);
        Serial.println(" ");
      // The accelerometer's maximum samples rate is 1kHz
    }
    void i2cWrite(uint8_t registerAddress, uint8_t data){
      Wire.beginTransmission(IMUAddress);
      Wire.write(registerAddress);
      Wire.write(data);
      Wire.endTransmission(); // Send stop
    }
    uint8_t* i2cRead(uint8_t registerAddress, uint8_t nbytes) {
      uint8_t data[nbytes];
      Wire.beginTransmission(IMUAddress);
      Wire.write(registerAddress);
      Wire.endTransmission(false); // Don't release the bus
      Wire.requestFrom(IMUAddress, nbytes); // Send a repeated start and then release the bus after reading
      for(uint8_t i = 0; i < nbytes; i++)
        data [i]= Wire.read();
      return data;
    }
     
  2. parovoZZ

    parovoZZ Гуру

    сделай
    наработай
    ищи лучше
    ты пойми - без труда не выловишь и рыбку из пруда.
     
  3. KindMan

    KindMan Гуру

    Так её там нет, переменной для включения светодиода.
    Её нужно создать, например
    Код (C++):
    uint8_t ledStatus;
    Потом включить порт светодиода на выход
    Код (C++):
    #define pinNumber 13
    pinMode(pinNumber, OUTPUT);
    А потом менять статус светодиода, в зависимости от значений kalAngleX и kalAngleY.
    Если расположите эти строки в программе правильно, помогу дальше.
     
    Tomasina нравится это.
  4. Ariadna-on-Line

    Ariadna-on-Line Гуру

    1. Возьмите любой скетч, типа Blink, где мигают светодиодами. Задайте точку подключения светодиода в своей программе.
    2. Получили данные из гироскопа. Вам нужно на них отреагировать должным образом. По-человечески - Если X=A - сделать то, если Y=B - сделать это. По-Ардуиньи - If (X==A) {....} // ("==" а не "=") и тд. А уж потом передавать в монитор.
    3. Истина - Если хочешь научиться программировать - программируй !!!
    ПС. Не забудьте поставить ограничительный резистор 150- 330 ом последовательно со светодиодом, чтоб не спалить Ардуину.
     
    Последнее редактирование: 9 апр 2019
  5. fogary

    fogary Гик

    По моему, Вы излишне усложняете простую задачу. Зачем сохранять статус светодиода?

    KatanaDie
    Учтите при проверке условия, что kalAngleX и kalAngleY вещественные переменные (т. е. имеют дробную часть).
    Светодиод должен включиться когда оба значения равны 150° или когда хотя бы одно из них? В каком состоянии должен быть светодиод, если значения будут больше или меньше 150° ?

    В общем виде, управлять светодиодом можно так, например:
    Код (C++):
    // вставить в конец функции loop()
    // pinLED - пин светодиода
    // вкл. - когда оба угла больше или равны 150°
    // выкл. - если оба или один из них меньше
    digitalWrite(pinLED, kalAngleX >= 150.0 && kalAngleY >= 150.0);
     
  6. KatanaDie

    KatanaDie Нуб

    Почти то, что нужно. Светодиод должен быть выключен, если X и Y не равны 150. Как только оба значения становятся равны 150 - светодиод горит. Поменял знак >= на ==, но это так не работает.

    Ну я же не сразу на форум полез, я предпочитаю всё делать самостоятельно, но тут я впал в ступор и не знаю, что делать дальше.
     
  7. parovoZZ

    parovoZZ Гуру

    Бери гистерезис. Ровно 150 не будет никогда.
     
    Ariadna-on-Line нравится это.
  8. fogary

    fogary Гик

    Как вариант:
    Код (C++):
    floor(kalAngleX) == 150.0 && floor(kalAngleY) == 150.0
    Или как советовали выше:
    Код (C++):
    (kalAngleX >= 150.0 && kalAngleX < 151.0) && (kalAngleY >= 150.0 && kalAngleY < 151.0)
     
    KatanaDie нравится это.
  9. KatanaDie

    KatanaDie Нуб

    Спасибо большое, второй код помог, заработало, только вот диод начинает гореть очень-очень слабо, можно совет по поводу того как это исправить?
     
  10. fogary

    fogary Гик

    С другим скетчем, наприер стандартный Blink, светодиод горит ярко?
    Как подключили светодиод, может номинал токоограничивающего резистора слишком большой?
     
  11. Ariadna-on-Line

    Ariadna-on-Line Гуру

    1.Правильно - включать светодиод между +5В и выводом. То есть включением будет
    digitalWrite(pin, LOW). Потому, что "нижний" транзистор вывода мощнее "верхнего", из-за технологии производства этих микросхем.
    2.Пробуйте разные выводы. Встречаются дохловатые. Не тянут нагрузку, хотя работают.
    3. Светодиоды попадаются дохлые, хотя редко.
    4. Резистор проверяйте прибором, а не по маркировке.
    ПС. Я встречался с такими "подвохами" в технике и деталях, что глаза на лоб... Отсюда и советы.
     
    Последнее редактирование: 10 апр 2019
    Un_ka нравится это.
  12. parovoZZ

    parovoZZ Гуру

    это где написано?
     
  13. KindMan

    KindMan Гуру

    Так все знают, что у двухъядерного процессора, одно ядро больше другова.
     
  14. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Не скажу - давно знаю. Молодые Самоделкины могут провести эксперименты. Признаю неправоту, - если докажут. Вообще - тема широкая - не для этой ветки.
     
    Последнее редактирование: 10 апр 2019
  15. KatanaDie

    KatanaDie Нуб

    Всего лишь забыл написать pinMode на выход, хех. Всё работает как надо, спасибо большое всем за помощь!
     
  16. Ariadna-on-Line

    Ariadna-on-Line Гуру

    И ниже. Левое.
     
  17. parovoZZ

    parovoZZ Гуру

    В даташите указано четко - 40 мА. Про то, что через нижний ключ можно ещё поддать - ни слова. У Attiny441/841 есть пара выводов под названием Extra High Sink I/O Pins. Разница в том, что "0" на таких выводах немного ближе к нулевому потенциалу, чем у остальных. Про ток - ни слова.
     
  18. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Extra High Sink - Экстра Высокий Сток, про extra low drop voltage - тоже ни слова.
     
  19. parovoZZ

    parovoZZ Гуру

    слов нет - есть графики. Выигрыш небольшой, но есть.