Соединение двух Arduino Uno по SPI...

Тема в разделе "Проводная и беспроводная связь", создана пользователем matwaysha, 2 май 2019.

  1. Belkin

    Belkin Гик

    Один символ в системе AVR всегда использует один байт, т.е. от "0" до "255".
    Дальнейший подсчет зависит от типа используемых значений.
    Вот и считайте... ;)
     
    matwaysha нравится это.
  2. Daniil

    Daniil Гуру

    ответ
    Начинайте читать про типы переменных.
    Вот пример моего алгоритма на псевдокоде
    Обратите внимание, что использовал Serial.print, а не write
    Код (C++):
    //передатчик
    loop_prd
    {
    float32_t X=-34.123412;
    delay(10000);
    Serial.print(":A");
    uint32_t tmp=(uint32_t)((X+90)*1e5);//5587658 избавляемся от знака минус и сохраняем нужное кол-во цифр после зпт.
    Serial.print(tmp,HEX);//0х5542CA
    Serial.print('\n');
    }

    //приёмник
    void serialEvent() {
      while (Serial.available()) {
        char inChar = (char)Serial.read();
        inputString += inChar;
        if (inChar == '\n') {stringComplete = true;}
      }
    }

    loop_prm
    {
        if (stringComplete)
        {
         
    //мы получили строку
            //0    1    2    3     4    5
            //0x3A 0x41 0x55 0x42  0xCA 0x13    в hex
            //':'  'A'  'U'  'B'   'Ê'    '\n'    в символах
            // 58   65   85   66    202    13        в dec
         
            //нужно найти индекс начала числа и конца числа
            цикл по i от 0 до inputString.Length-1 //тут могу ошибаться с вычислением длины
            {
                если inputString[i]=='\n'
                {
                    indxEND=i-1;//нас не интересует символ конеца строки
    //ответ indxEND=4
                }
                если inputString[i]==':'
                {
                    indxSTART=i+1;//нас интересует символ маркер
    //ответ indxSTART=1
                }
            }
            //далее всё нужно пихнуть в одну переменную

            цикл по i от indxSTART+1 до indxEND //indxSTART+1 перепрыгиваем через маркер, его обработаем позже
    //цикло по i от 2 до 4
            {
                uint32_t tmp=inputString[i];
                если i!=indxEND, тогда tmp=tmp<<8
    //проделаем по шагам
    //    i    tmp
    //    2    0x55
    //    2if    0x5500
    //    3    0x5542
    //  3if    0x554200
    //    4    0x5542CA
    //    4if    0x5542CA - if не сработал, т.к. конец (собрали число, которое и отправляли)
            }
            //запихиваем в нужную переменную
            Если inputString[indxSTART]=='A' тогда //если не 'А', то значит было отправлено другой угол, если вариантов много, то лучше использовать switch-case
            {
                X=(((float32_t)tmp)-90)/1e5; //делаем обратные преобразования
            }
        }
    }
     
    Последнее редактирование: 2 май 2019
    matwaysha нравится это.
  3. matwaysha

    matwaysha Нерд

    x и y сделал float, попытался реализовать. (n выполняет те же функции счетчика, чтобы через раз отправлять
    то один угол, то второй). Код получился такой: (как это работает я так и не понял, т.е. переменная объявляется в самом цикле, поэтому объявил её в начале
    )
    это передатчик
    Код (C++):
    void cout(){
      if(n == 1){
        Serial.print(":A");
        uint32_t tmp = (uint32_t)((x + 90)*1e3);
        Serial.print(tmp, HEX);
        Serial.print('\n');
        n = 2;
        return;
      }
       if(n == 2){
         Serial.print(":B");
        uint32_t tmp = (uint32_t)((y + 90)*1e3);
        Serial.print(tmp, HEX);
        Serial.print('\n');
        n = 1;
        return;
      }
    }
    это приемник
    Код (C++):
    void loop() {
      lcd.setBacklight(255);
      lcd.home(); lcd.clear();
      if(stringComplete = true){
        for(int i = 0; i < inputString.length(); i++){
          if(inputString[i] == '\n'){
            indexEnd = i - 1;
          }
          if(inputString[i] == ':'){
            indexStart = i + 1;
          }
        }
     
        for(int i = indexStart; i <= indexEnd; i++){
          tmp = inputString[i];
          if(i != indexEnd){
            tmp = tmp << 8;
          }
        }
        if(inputString[indexStart] == 'A'){
          x = (((float)tmp) - 90)/1e3;
        }
        else{
          x = (((float)tmp) - 90)/1e3;
        }
        tmp = 0;
      }

      if(y > 100){
        y = y - 256;
      }
      if(x > 100){
        x = x - 256;
      }
      lcd.setCursor(0,1);
      lcd.print(x);
      lcd.setCursor(8,1);
      lcd.print(y);

    }
    void serialEvent(){
      while(Serial.available()){
        char inChar = (char)Serial.read();
        inputString += inChar;
        if(inChar == '\n'){
          stringComplete = true;
        }
      }
    }
    Вроде бы смысл понятен, но экран снова показывает нули, значит я опять где - то ошибся, мне кажется, что это может быть связано с типами переменных... Но хоть смысл стал понятнее...
     
  4. Daniil

    Daniil Гуру

    не главное. Я пытался показать, что нужно любое число однозначно привести к положительному инту. Сколько байт это займёт в данном случае не важно, т.к. алгоритм от этого не поменяется.
    Как часто передатчик передаёт?
    Правильно ли вы соединили?
    Можно проверить посылку в программе HTerm, там и хексы и аски посмотреть можно.
    В этом цикле индекс начинается с символа А.
    Далее при копировании появилась ошибка:
    Если А то х=числу иначе х=числу.
    Где у?
    Проверка на превышение 100 выполняется? Если да, то что-то не то. Вы говорили, что угол от -90 до 90. Если угол будет меньше - 90, то я не могу сходу сказать чему будет равно
    Попрбуйте для отладки х и у присвоить заранее корректное число.
    Кстати, через hterm вы и приемник отладить сможете, в хексах формируете пачку руками и смотрите что сделает приемник.
    Также, на всякий случай, я бы объявил float z, присвоил бы какую-нибудь константу и вывел бы на экран. Чтобы убедиться, что lcd.print с float правильно работает.
     
    matwaysha нравится это.
  5. matwaysha

    matwaysha Нерд

    Видимо слишком ночью писал... Цикл исправил, у добавил, экран проверил, результаты не однозначные, поэтому довел до int x и y, на -90 проверил, там точно не бывает меньше. Правильность соединения проверил, даже провода другие поставил, чтоб точно знать период отправки сделал по таймеру, с учетом чередования отправляемых углов каждый угол отправляется каждые 20 миллисекунд, посылка, соответственно приходит каждые 10 миллисекунд (таймер тоже отдельно проверил). Ничего не помогло...
    А что такое hterm?
     
  6. Daniil

    Daniil Гуру

    HTerm
    начните с интервала по-больше.
    Для начала отладка, поэтому делайте так, чтобы руками можно проверить
     
    matwaysha нравится это.
  7. matwaysha

    matwaysha Нерд

    Ого! Спасибо, а как эту штуковину настроить именно под UART?
     
  8. matwaysha

    matwaysha Нерд

    Это прям очень странно, но я только что заметил, что не мигают светодиоды RX и TX на платах.
     
  9. Belkin

    Belkin Гик

    UART задействован ?
    Эти "ноги" в программе задействованы ?
    Если в обоих случаях "нет", то отчего им мигать ? ;)
     
  10. matwaysha

    matwaysha Нерд

    Передача пока идет именно по UART и платы соединены 0 пин - 1 пин; 1 пин - 0 пин, и GND ещё, вроде должны мигать, но не мигают. Я немного в замешательстве...
     
  11. Belkin

    Belkin Гик

    Передача идет ? Тогда оставьте разгадку "на сладкое"... ;)
    Вам связь нужна или "светодиодиком помигать" ? ;)
     
  12. matwaysha

    matwaysha Нерд

    А вот идет ли передача - это очень хороший вопрос, но когда передавал один угол без такого пакета, просто значение, всё передавалось.
     
  13. Belkin

    Belkin Гик

    "Отложите в сторону" разработку...
    Так заставьте одного только передавать, а второго только принимать, добейтесь устойчивой передачи и приема нужного пакета, а потом используйте наработки в основной программе.
    Вообще-то это "хороший тон" - разрабатывать и отлаживать программу поблочно/поэтапно.
     
    Daniil нравится это.
  14. Daniil

    Daniil Гуру

    обидно, что я не смог сказать яснее. Спасибо)
    никак, я думал, что ардуинки можно отлаживать отдельно. Использовать их разъем юсби.
    Если заработает по юсби, то заработает юарт. (для мк на плате ардуино это почти одно и то же).
    Подключите одну ардуинку к пк. Отработайте программу. Отложите. И повторите со 2ой.
    Hterm тут поможет идеально.
    (снизу программы, находится то что вы передаете. Там выберите hex и можете передавать вашему приемнику, то что нужно).
    В центре программы область приема, там ставите галочку на hex и будете видеть что передает ваш передатчик.
    Сверху программы настройки ком порта их выставляете как у вас на камнях.
    Кстати, везде параметры ком порта (и на ардуинках, и на пк) должны быть одинаковыми.
     
    Belkin нравится это.
  15. Daniil

    Daniil Гуру

    Разница между ком портом и юартом - только физика. Физика реализована промежуточной микросхемой. Поэтому когда вы отработаете программы с пк, то просто соедините две ардуинки и должно заработать.
    Вы помните, что при перепрошивке по юсби нельзя ни на что замыкать пины 0 и 1? (поэтому отработать с пк, даже легче)
     
  16. matwaysha

    matwaysha Нерд

    Понял. Попробую настроить. Возможно я сказал как - то не так, но у меня и есть только прием на одной и передача на другой. Просто удалось передать один угол, а не два.
     
  17. Belkin

    Belkin Гик

    Вам надо сразу разработать (придумать) алгоритм передачи пакета.
    Назовем его - "свой протокол"... ;)
    Указанная терминальная программа вам поможет.
    Я пользую Terminal v1.9b... Практически то же самое, но имеет русский интерфейс.
    Вообще-то их немало разных - на вкус и цвет... ;)

    Формируйте пакет, постепенно добавляя данные, смотрите, что "улетает" в терминал при передаче.
    И так - пока не заставите передавать пакет нужной длины.
    Отловите "косяки" передачи.

    Затем с тем же энтузиазмом начинайте бороться с приемом уже имеющегося пакета.
    Передатчиком будет тот же терминал.

    В таком варианте не придется "воевать" с двумя Ардуинами сразу... ;)
     
    Daniil нравится это.
  18. Belkin

    Belkin Гик

    matwaysha, у вас точно нет возможности передать данные между Ардуинами в параллельном виде или просто проигнорировали мое предложение в #15 ? ;)
     
  19. Belkin

    Belkin Гик

    И, самое главное - используйте не USB Ардуины, а переходник USB-UART, подключаясь к пинам RXD и TXD.
    Могу ошибаться, но USB Ардуины работает с SPI, а не с UART...
     
    Последнее редактирование: 3 май 2019
  20. Daniil

    Daniil Гуру

    я такое не видел. Вот схема. Где есть ft232 или СР, то там точно через юарт.
    Мы же про уну?
     
    Belkin нравится это.