Шаговый двигатель + тензодатчик = дозатор -нужна помощь.

Тема в разделе "Arduino & Shields", создана пользователем Valik, 23 окт 2018.

  1. Valik

    Valik Нерд

    Доброго дня. Прошу помощи в решении кода к дозатору. Если в кратце сказать то проблема в следующем:
    есть шаговый двигатель Nema23+driver+блок питания, работает как обычный двигатель. Через команду миллис его подключил к ардуино - проблем нет, крутится - вертится. И с нужной скоростью. Но как только в функцию loop () добавляю данные для опроса тензодатчика "scale.get_units();" шаговик перестает работать вообще, не крутится, какието звуки издает но не более.. Тензодатчик обычный китайски со стандартной библиотекой, работает и вес показует.
    Почему шаговик перестает работать ума не приложу. Может кто то поможет, был бы благодарен.
    Скетч прилагаю:
    int ledState = LOW;
    unsigned long previousMillis = 0;
    const long interval = 65; //задержка между сигналами HIGH и LOW в микросекундах
    const int stepPin = 6; // на этот пин подается сигнал HIGH или LOW для драйвера, с которого происходит управление шаговым двигателем
    const int dirPin = 5; // незнаю точно для чего, наверное аварийный стоп, в процессе не используется
    const int enPin = 7;

    #include "HX711.h"
    HX711 scale(A1, A0);
    float calibration_factor = 13; //13.3 13.3 калибровка!
    int units;
    //int ves;

    void setup() {
    pinMode(stepPin,OUTPUT);
    pinMode(dirPin,OUTPUT);
    pinMode(enPin,OUTPUT);
    digitalWrite(enPin,LOW); // HIGH или LOW вращение по часовой или против часовой стрелки

    Serial.begin(9600);
    scale.set_scale();
    scale.tare(); //Сбрасываем на 0
    scale.set_scale(calibration_factor); //Применяем калибровку
    }

    void loop() {
    // считываем и выводим в порт данные о весе
    int ves;
    Serial.print("Reading: ");
    units =+ scale.get_units();
    ves = units * 0.035274; // переводим унции в граммы
    Serial.println( ves);
    //////////////////////////////////////

    // управление шаговым двигателем без веса, работает чудесно, но как только подключается аналоговый сигнал с тензодатчика то двигатель вообще не крутится
    unsigned long currentMillis = micros();
    if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;
    if (ledState == LOW)
    ledState = HIGH;
    else
    ledState = LOW;
    // устанавливаем состояния выхода, чтобы подать на него высокий или низкий сигнал
    digitalWrite(stepPin, ledState);
    }
    }
     

    Вложения:

  2. DIYMan

    DIYMan Guest

    Сажай управление шаговым на прерывания - и будет счастье. Можешь поюзать библиотеку TimerOne - годная. Учти также, что HX711, по даташиту - надо быро опрашивать, если на ноге CLK висит один уровень дольше 60 us (емнип) - то HX711 свалится в сон. Поэтому лучшим вариантом будет читать с HX711 в тот момент, когда шаговый стоит. Ну или убедиться, что вписываешься во временнЫе интервалы, как минимум.

    А вообще - каждый проход loop опрашивать весы - такое себе занятие, дикое.
     
    DetSimen и Valik нравится это.
  3. parovoZZ

    parovoZZ Гуру

    так для начала надо почитать про устройство МК, как выполняется программа.
     
  4. DetSimen

    DetSimen Guest

    Наерна это состояние и называется "в зобу дыханье спёрло" от возмущенья.
     
  5. Valik

    Valik Нерд

    Спасибо за направление где искать нужно.
     
  6. Valik

    Valik Нерд

    я не силен в программировании, и поэтому все данные беру из ютюба, хватило мозгов пока что, на то, что бы обойти функцию delay. Думал miliis поможет, но не тут то было.
     
  7. parovoZZ

    parovoZZ Гуру

    А ютуб это учебник какой?
     
  8. Valik

    Valik Нерд

    А вообще - каждый проход loop опрашивать весы - такое себе занятие, дикое.[/QUOTE]

    По примеру из библиотеке TimerOne, там задали задержку для мигания светодиода и он мигает.
    Я так понимаю, что TimerOne библиотека может решить задачу шагового двигателя и он будет крутится с задержкой в 65 микросекунд в независимости от того что происходит в void loop(). Но есть одно "но" - можно эту задержку в зависимости от полученных данных с тензодатчика увеличить программно, к примеру 100, 300, 500 микросекунд?

    Тоесть поясню: дозатор = ШД (шаговый двигатель) до 400 грамм использует задержку в 65 милисекунд (скорость вращения очень быстрая), от 400 до 480 - 200 милисекунд(скорость вращения средняя), от 480 до 500 грамм - 500 милисекунд (скорость вращения медленная). Такой процесс необходим для точности дозировки.
     
  9. parovoZZ

    parovoZZ Гуру

    абдурина на это не рассчитана. Если надо всё расставить по микросекундам - это в си или даже асм.
     
  10. DIYMan

    DIYMan Guest

    А почитать документацию к библиотеке TimerOne и увидеть, что там есть метод setPeriod ? Всё там можно, короче.
     
  11. DIYMan

    DIYMan Guest

    Миллисекунды - всё это очень медленно :) 500 миллисекунд - это полсекунды, т.е. всего 2 шага в секунду. Всё можно сделать с использованием TimerOne, за полчаса - задача тривиальнейшая.
     
  12. Valik

    Valik Нерд

    Спаибочки :)
     
  13. b707

    b707 Гуру

    Потому что библиотека HX711 написана криворуким новичком. Она блокирующая, фактически на delay-ях, пока идет опрос весов - программа стоит. А если весы почему-то не отвечают - все тупо виснет.
     
  14. DIYMan

    DIYMan Guest

    Ну не совсем там там всё печально: да, некоторые функции надо посадить на таймаут, чтобы не висло, когда HX711 отвечает. А вот чтение - там никак без блокирующего кода, ибо читать с HX711 надо быстро. Скажем, через MCP23017 - уже скорости не хватает, при чтении HX711 валится в сон, согласно даташиту.

    Ни одного delay в библиотеке нету, к слову. Возможно, мы о разных говорим.
     
  15. b707

    b707 Гуру

    Настоящих делаев там нет, но концепция та же. Насчет "валится в сон" - не замечал И в даташите такого что-то не вижу. Я с HX711 работаю примерно так же, как с DS18B20 - то есть заказал чтение веса и ушел. Потом через полсекунды вернулся - принял результат. И ничего не засыпает.
     
  16. DIYMan

    DIYMan Guest

    Ты немного не понял. Да, в библиотеке есть ожидание, пока на DOUT не появится низкий. Это хрен с ним, с этим можно жить. Само чтение, вот тут:
    Код (C++):
        // pulse the clock pin 24 times to read the data
        data[2] = shiftIn(DOUT, PD_SCK, MSBFIRST);
        data[1] = shiftIn(DOUT, PD_SCK, MSBFIRST);
        data[0] = shiftIn(DOUT, PD_SCK, MSBFIRST);
    И вот тут, согласно даташиту:
    Если уровень на PD_SCK держится высоким больше 60 микросекунд - всё, датчик в сон. Попробуй для интереса подключить его на MCP23017, заменив shiftIn на такое же чтение с портов MCP. В лоб - не взлетит, скорости обмена по шине не хватит. Тайминги я не замерял, но есть подозрение, что датчик валится в сон. Именно об этом я писал, что надо читать с датчика быстро.

    В остальном - библиотека вполне рабочая, читать с весов каждый проход loop - в любом случае дичь, согласись ;) По остальному - в функциях есть кол-во чтений, необязательно читать 10 раз подряд, можно самому читать через промежутки времени, заведомо большие времени конверсии, накапливать, и делать average - в библиотеке, если посмотреть, просто тупое
    Код (C++):
    float HX711::get_units(byte times)
    {
        return get_value(times) / SCALE;
    }
     
    Короче, жить можно :) Да и, при желании - всегда можно дописать неблокирующий код, с учётом времени конверсии. Впрочем, лично я пока - не напрягаюсь особо - просто при старте делаю проверку сам, что на DOUT низкий уровень, и если я там его не нашёл в течение таймаута - всё, весы не подключены. А что там может поломаться - да ничего, если только физически чего не коротнёт. Но это уже - нештатка. Вот у меня, кусок кода чтения с весов:
    Код (C++):
     uint32_t startTime = millis();
        while(!scale->is_ready())
        {
          if(millis() - startTime > 200) // не готовы за 200 мс, ждать дальше нечего
            return -1.0; // если возвращённое значение меньше нуля - с весов нет данных
        }
    scale->set_gain();
    ......
    Читаются редко, yield использую, проблем с блокировкой - нету ;)
     
  17. Valik

    Valik Нерд

    Помогите еще в одном разобраться. Мне удалось добится следующего:

    Timer1.initialize(100); // 100 быстро, 200 средне, 300 медленно - чем или как можно програмно изменить число со 100 на 200:confused:
    Timer1.pwm(9, 512); // полсекунды светимся (512 / 1024), на полсекунды гасим, ставил и 64 вместо 512 эфекта нет
    Timer1.attachInterrupt(Timer1_action);
    ////
    void Timer1_action()
    {
    if (ves <= 50){ // если вес больше 50 грамм шаговик останавливается, в принципе то что мне и нужно :D
    digitalWrite(9, !digitalRead(9));

    Не могу нигде примера найти как работает setPeriod, если несложно покажите примером, нубу. Недогоняю просто.
     
  18. DIYMan

    DIYMan Guest

    Когда нужно изменить период:
    Код (C++):
    Timer1.setPeriod(тут период в микросекундах);
    Несложно, правда?
     
  19. ostrov

    ostrov Гуру

    Это про таймеры STM32 под IDE чтоли разговор?
     
  20. vvr

    vvr Инженерище

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