Песочница

Тема в разделе "Флудилка", создана пользователем CYITEP_BAC9I, 31 янв 2019.

  1. Asper Daffy

    Asper Daffy Гуру

    Сусемьбек, А Вы бы печатали свою переменную button - узнали бы много интересного. Вот попробуйте.
     
    Последнее редактирование: 5 фев 2019
    DetSimen нравится это.
  2. AlexU

    AlexU Гуру

    Думаю в этой "песочнице" стоит немного прояснить ситуацию.
    Все функции вывода в последовательный порт (типа Serial.print, Serial.write....) задумывались как не блокирующие. Т.е. возварт из функции происходит, не дожидаясь отправки всего сообщения в линию. Помогает в этом буфер передачи Serial интерфейса. И вот тут-то и начинается самое интересное -- пока в буфере есть свободное место, данные кладуться в буфер и происходит возврат из функции, и далее за освобождение буфера отвечает обработчик прерывания отправки данных Serial (UART0_UDRE_vect). А если в буфере места мало, то функция превращается в блокирующую -- будет ждать пока буфер не освободится.
    И вот теперь смотрим на прерывание. Если в буфере не будет места, то функция заблокирет работу обработчика прерывания, пока буфер не освободится. А буфер не может быть освобождён из-за того, что обработка прерываний запрещена (ещё обработка другого прерывания не завершена). Вот и получили типичный deadlock.
     
    Сусемьбек нравится это.
  3. AlexU

    AlexU Гуру

    Как ты мог свои золотые руки и чистые мысли обгадить этой ненавистной Абдуриной? Думаю, отрасль не переживёт такой утраты...
     
    Airbus нравится это.
  4. parovoZZ

    parovoZZ Гуру

    Так вашими молитвами)
     
  5. Всем большое спасибо. Скорее всего так, из за вывода в сериал, потому что когда нажимал с паузами, было нормально. 2а быстрых нажатия == зависание. Переправил немного скетч , сделав проверку в прерывании. Ночером доберусь до компа (искренне надеюсь), проверю. Все, загрузил Дуню по полной, в фоновом режиме сейчас она и шимит и контролирует напряжение и считает импульсы) . Большего наверное уже не выжать.
    Код (C++):
    volatile byte buttons =0;
    bool          A = false;
    uint32_t      buttons_Time =0;

    ISR(PCINT1_vect)
    {
    //добавил проверку запрещать прерывания только если было нажатие кнопки
    // и ничего не делать если кнопку долго держали и отпустили
    //это исче одна ошибка помимо Serial.println
      if (PINC>0 )
    {
       buttons = PINC; //передаем данные о портах в переменную buttons
       PCICR &= ~(1 << PCIE1); //запрещаем прерывания на линии C
       buttons_Time = millis();
    }

    }

    void setup()
    {DDRC = 0b00000000;
    PCMSK1 = 0b00001111;  // разрешаем прерывания на пинах А0, А1, А2, А3
    PCICR |= (1 << PCIE1);
    Serial.begin(9600);
    }
    void loop()
    {

    if( buttons >0  ) //если произошло кокоето измениее в состоянии портов
    {
        switch (buttons)
        {
                case 0b00000001:    //была нажата кнопка А0
    Serial.println("knopka111");
    Serial.println(buttons);
                break;

                case 0b00000010:    //была нажата кнопка А1
    Serial.println("knopka222");
    Serial.println(buttons);
                break;

                case 0b00000100:     //была нажата кнопка А2
    Serial.println("knopka333");
    Serial.println(buttons);
                break;

                case 0b00001000:     //была нажата кнопка А3
    Serial.println("knopka444");
    Serial.println(buttons);
                break;  
           
        }
        if( millis() - buttons_Time > 50 )  // своеобразный антидребезг

        {
            //разрешаем прерывания на линии C
            PCICR |= (1 << PCIE1);
            //обнуляем переменную
            buttons =0;
        }
    }
    }
    П.с. контролировать длительность нажатия и отпускание кнопки мне не нужно. Поэтому и проверка нажатий такая простая.
     
    Последнее редактирование: 5 фев 2019
  6. Попробовал, выдает 1,2,4,8
     
  7. Asper Daffy

    Asper Daffy Гуру

    Неправильно попробовал. Так не пробуют. Запустите и пусть себе выдаёт. Дождитесь зависания и вот тогда и посмотрите. А так-то что толку, что она выдаёт.
     
  8. Если утонешь, домой не приходи.
    Когда она зависает, почему-то ничего не передаёт). Но если правильно понял намек, добавлю ещё одну проверку. Если пришло что то непонятное, сбрасывать все нахрен, и по новой получать данные.
     
  9. Asper Daffy

    Asper Daffy Гуру

    Блин, да сделайте Вы это, наконец, чем теоретизировать-то! Полюбуетесь, что она Вам выдаст последнее перед зависанием! Предсмертный вздох, так сказать! Сделали бы что Вам говорят - давно бы проблема решилась!

    Только надо не проверки ставить, а порт правильно читать. Но Вы сначала посмотрите что выдаётся - там поймёте.
     
    Сусемьбек нравится это.
  10. AlexU

    AlexU Гуру

    Есть несколько ошибок в коде, которые по счастливой случайности пока не выдают себя.
    Во-первых накладывайте маску, тогда будете получать ровно то, что надо:
    Код (C++):
    ISR(PCINT1_vect) {
      // интересуют только младшие четыре бита порта
      buttons = PINC & 0x0F; //передаем данные о портах в переменную buttons
      PCICR &= ~(1 << PCIE1); //запрещаем прерывания на линии C

    buttons_Time = millis();
    }
    Во-вторых таким способом дребезг вы не поборите. Проблема аналогична обсуждаемой ранее, в другой теме.
    Решение можно применить аналогичное, но скорее лучше не отключать прерывания PCINT1 и следить за флагами, а маскировать через PCMSK1, тогда флаги взводиться не будут.
     
    Последнее редактирование: 5 фев 2019
    CYITEP_BAC9I и Сусемьбек нравится это.
  11. Asper Daffy

    Asper Daffy Гуру

    Блиин! Я уж который час пытаюсь подвести ТС к тому, чтобы он сам это понял по отладочной печати и решил проблему самостоятельно! А Вы сразу на тарелочке :(
     
    Сусемьбек нравится это.
  12. Спасибо. Доберусь до компа проверю, если не усну.
     
  13. AlexU

    AlexU Гуру

    Вот, что выдаёт отладочная печать:
    Может не используемые ноги к земле притянуты. Вы же устройства не видите. Поэтому вероятность понять проблему по отладочной печати стремиться к нулю.
     
  14. Asper Daffy

    Asper Daffy Гуру

    Да, неужели! Вы на код-то гляньте.
     
  15. Поправил немного вариант2. Сделал сброс флага, на всякий случай. Вкл выкл по маске PCMSK1. Что то вроде антидребезга. Если все норм будет отпишусь за результат. Можно конечно и побитово читать порт С, не хочу однако.
    Код (C++):
    volatile byte buttons =0;
    bool          A = false;
    uint32_t      buttons_Time =0;

    ISR(PCINT1_vect)
    {   buttons = PINC & 0x0F;
      if (buttons>0 )
    {
    //передаем данные о портах в переменную buttons
      // PCICR &= ~(1 << PCIE1); //запрещаем прерывания на линии C
      PCMSK1 = 0b00000000;
       buttons_Time = millis();
    }

    }

    void setup()
    {DDRC = 0b00000000;
    PCMSK1 = 0b00001111;  // разрешаем прерывания на пинах А0, А1, А2, А3
    PCICR |= (1 << PCIE1);
    Serial.begin(9600);
    }
    void loop()
    {
    byte G =PINC & 0x0F;
    if( buttons >0 && millis()-buttons_Time>50 &&G >0 ) //если произошло кокоето измениее в состоянии портов
    //и оно держится более 50 мск то начинаем расшифровку что пришло
    {
        switch (buttons)
        {
                case 0b00000001:    //была нажата кнопка А0
    Serial.println("knopka111");
    Serial.println(buttons);
                break;

                case 0b00000010:    //была нажата кнопка А1
    Serial.println("knopka222");
    Serial.println(buttons);
                break;

                case 0b00000100:     //была нажата кнопка А2
    Serial.println("knopka333");
    Serial.println(buttons);
                break;

                case 0b00001000:     //была нажата кнопка А3
    Serial.println("knopka444");
    Serial.println(buttons);
                break;  
           
        }
     
           PCIFR &= ~(1 << PCIF1); //снимаем флаг прерывания хотя в моем случае наврное лишнее
           // PCICR |= (1 << PCIE1);
            PCMSK1 = 0b00001111;
            //обнуляем переменную
            buttons =0;
     
    }
    }
     
  16. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    эт снова я.
    доброй ночи. всем спасибо все работает. повесить дуню не получилось как ни пытался. все нажатия обрабатываются четко, без малейшего намека на дребезг. единственно думаю что снимать флаг прерываний перед разрешением прерываний это лишнее
    теперь хочу воплотить задумку с прогресс барами на дозиметре движущимися справа на лево и отражающие количество зафиксированных частиц в секунду.
    пока что накидал примерно следущее
    Код (C++):
    const byte array_size =84; // количество ячеек массива по количеству пихелов ширины экрана
    int Received_data [array_size]; // массив для хранения полученных данных
    int Scaled_data [array_size]; // массив с масштабированными значениями в длинах линии
    //const int zero_cell; //переменная для записи ачейки с адресом 0
    int random_data, x, y ,x_2, y_2;
    void setup()
    {

    }
    void loop()
    {
        //сдвигаем массив циклически
    for(byte i = 1; i < array_size; i++)
        {
       Received_data[i-1] = Received_data[i];    
        }
        //заполняем массив случайными значениями, позднее сюда будут зписыватся данные с датчика
        // каждые 0.5 или 1 секунду
    Received_data [83] = random (410); //крайнему правому элементу массива присваеваем данные с датчика

    //длина бара 14 пихелов поэтому масштабируем полученные значения в новый массив
    //
    for(size_t i = 0; i <=83; i++)
        {    
            Scaled_data [i] =map(Received_data [i], 1, 410, 1, 14);    
    }
    //дальше самое страшное, вывод на экран
    //сильно упрощает задачу что данные обновляются со сдвигом элементов влево
    //остается только задать координаты линии и вывести на экран
    //нижняя граница по y c координатами 47
    //максимальная верхняя у 34


    //рисуем белый прямоугольник чтоб забить предидущую информацию
    display.fillRect(0, 34, 83, 47, WHITE);
    display.display();
    //пытаемся вывести графическую информацию
    //скоре всего циклом for поскольку число элементов массива равно числу пихелов по ширине экрана
    for(size_t i = 0; i <= 83; i++)
    {
    //как то надо вычислить координаты линий, длина линий есть в массиве Scaled_data []
    //х,у верхние координаты начала линии, х_2, у_2 нижние координаты , думаю что можно их перевернуть
    //дальше я впадаю в глубокую печаль и иду спать
        drawLine(x, y, x_2, y_2, BLACK);
    }

    display.display();
    }
     
    скорее всего бред, но надо же с чего то начать.
    всем спасибо и хороших снов.
     
    Последнее редактирование: 5 фев 2019
  17. Ночер всем добрый. предварительно накидал скетчик для плюшки с движущимися ,барами линиями. Показывающий в графическом виде количество зарегистрированных распадов в секунду. Ничего сложного, поначалу правда сбивало с толку много переменных координат и их вычисление.
    Понимаю что немного нестандартная тема, но кто глянет, и хоть примерно поймет что я делаю), подскажите есть ли способ сделать это проще?

    Работоспособность пока не проверял. Только через сутки получится.

    Код (C++):
    const uint8_t array_size =84; // длина массива== ширине экрана в пихелах
    uint16_t Received_data [array_size]; //массив для сохраниния зарегестрированных частиц в секунду
    //uint16_t Scaled_data [array_size];
    //const int zero_cell; //переменная для записи ачейки с адресом 0
    uint16_t random_data;
    uint16_t particles_second =0; //переменная для сохраниния зарегестрированных частиц в секунду
    uint16_t dose_limit =410; //предел масштабирования дозы
    uint8_t x_top, x_bottom ; // координаты Х линии зебры
    uint8_t y_top;
    uint8_t y_bottom = 47; // координата Y нижнего края линии
    bool zebra_update =0; // выбор момента обновления зебры
    void setup()
    {

    }
    void loop()
    {
    //сдвигаем массив на 1 элемент влево
    for(byte i = 1; i < array_size; i++)
    {
    Received_data[i-1] = Received_data[i];
    }
    //в крайнюю правую ячейку массива помещаем свежие данные с датчика
    Received_data [83] = particles_second; // (410)

    //если пришло время обновить "зебру"
    if ( zebra_update)
    {
    //рисуем белый прямоугольник чтоб забить предидущую информацию
    display.fillRect(0, 34, 83, 47, WHITE);
    display.display();
    //в цикле вычисляем координаты линии
    for(size_t i = 0; i < array_size; i++)
    {
    //координаты Х верхней и нижней границы по вертикали совпадают
    // координата Y нижней точки линии всегда одна 47
    x_bottom = i;
    x_top = i;
    //вычисляем верхнюю координату y
    // из 47 вычитаем масштабированное в пределах 1-14
    y_top = y_bottom - map(Received_data [i], 1, dose_limit, 1, 14); //drawLine(x, y, x_2, y_2, BLACK);
    drawLine(x_top, y_top, x_bottom, y_bottom, BLACK);
    }
    //ну и самое желаемое
    display.display();
    }
    }
    Как думаете , заработает?
     
    Последнее редактирование: 6 фев 2019
  18. Доброго времени суток. Улучшаю познания в области указателей на функции. Нашел такой пример
    Код (C++):
    //Только для             void (const char*)
    #include <iostream>
    using std::cout;
    using std::cin;
    void foo1(const char* S){
        cout << "foo1:  " << S << '\n';
    }
    void foo2(const char* S){
        cout << "foo2:  " << S << '\n';
    }
    void foo3(const char* S){
        cout << "foo3:  " << S << '\n';
    }
    int main(){
        void ((*arr[3]))(const char*); //Создали массив с 3 ячейками под функции
        /*В любую ячейку в нужный момент можно присвоить адрес функции*/
        arr[0] = foo3;
        arr[1] = foo1;
        arr[2] = foo2;
        /*И использовать ячейку, хранящую адрес функции, как функцию*/
            arr[0]("HELLO");     //с помощью указательной переменной запускаем функцию
            arr[1]("World");
            arr[2]("GRAND!!!");
        cin.get();
    }
    Не совсем понял момент . Как " использовать ячейку, хранящую адрес функции, как функцию"? Это как? Как ячейка с адресом функции может вместить в себя функцию?
    Добавил позднее.
    Сорри все понял, я не обратил внимание на сивол S в скетче. Сам ответил на вопрос)
     
  19. AlexU

    AlexU Гуру

    Небольшое дополнение. В языках C/C++ есть такое понятие как оператор '()' -- оператор 'скобки'. Этот оператор, говорит, что нужно вызвать функцию, которая находится по адресу, определяемому переменной. Вот пример:
    Код (C++):
    unsigned long
    my_func()
    {
      puts ("'my_func()' called");
      return 10;
    }

    int
    main (void)
    {
      unsigned long var;

      // в переменную var записываем адрес функции 'my_func'
      // скобок нет -- нет вызова функции
      //+ делаем явный cast, что бы компилятор не ругался
      var = (unsigned long) my_func;

      // скобки есть -- будет вызвана функция 'var()',
      // которая по сути является функцией 'my_func()'
      // в результате вызова функции 'var' будет присвоено
      // значение '10' переменной 'var'
      //+ делаем явный cast, что бы компилятор не ругался
      var = ((unsigned long (*)()) var)();

      // скобок нет -- нет вызова функции
      printf("var: %ld\n", var);

      return EXIT_SUCCESS;
    }
    Результат работы такой программы:
    Код (Text):
    'my_func()' called
    var: 10
     
    Сусемьбек и DetSimen нравится это.
  20. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    доброй ночи всем. решил добавить еще одну плюшку своей опупеи с дозиметром.
    Сохранение данных накопленной дозы и времени работы датчика (у него ресурс ограничен).
    В схеме ничего нового из области аварийного сохранения данных при пропадании питания нет. (забыл выключатель нарисовать)
    отличие в том что "жрущие" нагрузки подключены после источника питания до диода (условно показан эл.двигатель). а микросхема берет питание после диода. суть в следующем, при выключении питания, первым делом отрубаются все трансформаторы, подсветки, экранчики. Дуня уходит в прерывание по сигналу с А5 пина, где сохраняет накопленную за текущий сеанс дозу и время работы датчика. как думаете будет такая схема работать? думаю С1 найти на 4700 мкф, должно хватить на сохранение данных. есть еще ионистор на 1 F, но он собака долго заряжается (через ограничительный резистор) около 1 минуты. 0.1F был бы самое то, но его нету

    scrin pitanija.jpg