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

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

  1. Daniil

    Daniil Гуру

    Не перепутали с интерпретацией того что вам дисплей выводит (по вашим же координатам)? должно быть End=4, Length=6.
    А tmp?
     
  2. Daniil

    Daniil Гуру

    вы отправляете 3A 41 02 0F 58 0A
    индекс меняется от 0 до 5, а длина 6 символов.
    'A' это 41 - имеет индекс 1
    58 - последний код числа, имеет индекс 4.
     
  3. matwaysha

    matwaysha Нерд

    tmp вообще не выводится, сейчас ещё раз проверил, там точно такие данные.
     
  4. matwaysha

    matwaysha Нерд

    он так выводит:

    6
    4 1
    ^ с этой стороны начало дисплея.
     
  5. Daniil

    Daniil Гуру

    а если?
    lcd.setCursor(5,0); \\ 0 -1ая строка, 5 - 5ый символ в строке.
    lcd.print(m);
    по моему плану шетёрка должна переместиться вправо.
     
  6. matwaysha

    matwaysha Нерд

    Что - то я да... Шестерка съехала, это длина.
     
  7. matwaysha

    matwaysha Нерд

    Таки сделал вывод tmp, но только для первой пришедшей строки. Вот то, что он вывел
    4337720
     
  8. Daniil

    Daniil Гуру

    Так, пачку получили. Нашли внутри неё где хранится число теперь его нужно вынуть. Вытаскивать попробуем через, простите, жопу.
    Нужно объявить массив байтов (где нибудь вверху, глобально)
    Код (C++):
    byte tmp_mas[10];\\ возьмём с запасом
    Далее, перепишем этот кусок:
    Код (C++):
        for(int i = indexStart + 1; i <= indexEnd; i++){
          tmp = tmp + inputString.charAt(i);
          if(i != indexEnd){
            tmp = tmp << 8;
          }
        }
    на такой
    Код (C++):
    inputString.getBytes(tmp_mas, 10);\\надесь тут мы вытащим кодики символов
        for(int i = indexStart + 1; i <= indexEnd; i++){
          tmp = tmp + tmp_mas[i]; \\ту наконец таки будем обращяться к кодикам
          if(i != indexEnd){
            tmp = tmp << 8;
          }
        }
    сработает?
     
  9. Daniil

    Daniil Гуру

    Перепутал скобочки...исправил код - обновите страницу
     
  10. Daniil

    Daniil Гуру

    Что? я не ожидал) как это так?
     
  11. matwaysha

    matwaysha Нерд

    Виноват, он там выводит значение, но не той штуки...
     
  12. Belkin

    Belkin Гик

    Я про это говорил с самого начала: "определить длину пакета для передачи/приема"... ;)
    Допустим, это будет 10 байт...

    Каждому значению определим позицию:
    1 байт - угол X
    2 байт - угол Y
    3 байт - угол Z
    4 байт - ускорение X
    ... и так далее до 10.
    Перед передачей пакета записываем в нужные позиции значения, остальные можно не изменять или обнулять, смотря что нужнее.

    На принимающей стороне побайтно заполняем массив и из него уже, зная позиции (см. выше) берем нужные данные.
     
  13. Daniil

    Daniil Гуру

    Мы сбежали в личку, а то ждать по 10 мин на реакцию совсем не то.
    Я в шоке от стрингов( Работали бы с массивом чаров проблем не знали.
     
    Belkin нравится это.
  14. Belkin

    Belkin Гик

    Понял. Удачи ! ;)
     
    Daniil нравится это.
  15. parovoZZ

    parovoZZ Гуру

    Я с UART работаю так:
    Код (C++):

    void UART_Init (uint16_t ubrr)
    {
        UBRR0H = (uint8_t) (ubrr >> 8);
        UBRR0L = (uint8_t) ubrr;

        UCSR0B = (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (1 << RXEN0) | (1 << TXEN0);

        UCSR0C = (3 << UCSZ00);        // 1-stop bit, 8 bit data
    }

    void UART_Transmit (uint8_t data)
    {
        while (!(UCSR0A & (1 << UDRE0)))
        ;
        UDR0 = data;
    }

    uint8_t UART_Receive (void)
    {
        while (!(UCSR0A & (1 << RXC0)))
        ;
        return UDR0;
    }
    в main.c пишу :
    Код (C++):

    #define F_CPU        16000000UL

    // ... Определение скорости работы UART
    #define baud        250000
    #define ubrr        F_CPU/16/baud - 1
    Перед главным циклом вставляю
    Код (C++):
        UART_Init(ubrr);

        UART_Transmit(100);
        UART_Transmit(0);
     
    Belkin и Daniil нравится это.
  16. Daniil

    Daniil Гуру

    Мы победили.
    Я сам начинал с аналогичной задачи, поэтому рьяно советовал решить проблему так, как я её решал в своём "детстве". Мне стыдно, что на таких элементарных процедурках забуксовал, но зато ещё раз всё вспомнил и научился кое-чему новому.
    Но я всё позабыл, на что и напоролся. Понасоветовал всякого. Мне ближе работать с примитивными типами, чем со стрингами.

    В итоге пришли к такому варианту:
    Код (C++):
    передатчик
    if(stringComplete == true){
        indexEnd=inputString.indexOf('\n')-1;    //индекс последнего символа числа
        indexStart=inputString.indexOf(':')+1;    //индекс канала (за ним идёт первый символ числа)
        inputString.getBytes(tmp_mas, 10);        //превращаем стринги в массив чаров
        for(int i = indexStart + 1; i <= indexEnd; i++){ //цикл по символам числа
          tmp = tmp + tmp_mas[i];    //накапливаем данные
          if(i != indexEnd){        //если символ числа последний, то сдвиг не нужен
            tmp = tmp << 8;
          }
        }
        if(inputString.charAt(indexStart) == 'A'){
                            //если канал А, то это х
          x = (((float)tmp)/1.0e3) - 90.0;
        }
        else{                //иначе, то это y
          y = (((float)tmp)/1.0e3) - 90.0;
        }
        tmp = 0;//обнуляем всё
        stringComplete = false;
        inputString = "";
      }
    Стринги копируем в массив чаров размером 10: 3 байта служебная информация (":", "A/B" и "\n"). 4 байта на uint32_t. Итого нужно 7. Если проверить максимальный угол, то его "код" занимает не более 3ёх байт, поэтому массив можно сделать размером в 6 элементов. Но сделали в 10 для того, чтобы не париться.
    Код (C++):
    приёмник
    void cout2(){
        byte bt;
        uint32_t tmp = (uint32_t)((x + 90.0)*1.0e3);    //получаем инт из угла
        switch (n)            //подготовка посылки с заделом на расширение каналов
        {
            case 1:
                Serial.print(":A");
                n=2;
                break;
            case 2:
                Serial.print(":B");
                n=1;
                break;
        }
        for (int i=3; i>=0; i--)    //цикл от старшего байта к младшему
        {
            bt=(tmp>>8*i) & 0xFF;         //i-ый байт, маска лишней не бывает. Хоть тут и байт.
            if ((bt>0) || (i==0)){        //если там не нули ИЛИ младший байт, то не выводим
                                        //если число 0, то хоть 1 байт, но нужно вывести
                Serial.print(bt, BYTE); //отправляем байт
            }
        }
        Serial.print('\n');//конец строки/пачки
    }
    Вот примеры хексов пачек данных.
    0x3A - ':' - начало пачки
    0x41 - 'A' - канал Х
    0x0A - '\n' - конец пачки
    Код (C++):
    3A 41 00 0A - 0x00 - код 0 - получаем -90 (минус)
    3A 41 AF C8 0A - 0xAFC8 - код 45000 - получаем -45
    3A 41 01 5F 90 0A - 0x15F90 - код 90000 - получаем 0
    3A 41 02 0F 58 0A - 0x20F58 - код 135000 - получаем 45
    3A 41 02 BF 20 0A - 0x2BF20 - код 180000 - получаем 90
    3A 41 01 24 94 0A - 0x12494 - код 74900 - получаем -15.1 (74900/1e3-90=-15.1)
    Основной посыл был правильным, да в реализации подкочал, да и утомлённость брала своё.
     
    Последнее редактирование: 4 май 2019
    Belkin нравится это.
  17. Belkin

    Belkin Гик

    Я бы все-таки остановился на одинаковом размере "пакета".
    Удобнее... Можно было бы и без лишней передачи "0x0A - '\n' - конец пачки" обойтись... ;)
    Выглядело бы так (из вашего примера):
    Код (C++):
    3A 41 00 00 00 - 0x00 - код 0 - получаем -90 (минус)
    3A 41 AF C8 00 - 0xAFC8 - код 45000 - получаем -45
    3A 41 01 5F 90 - 0x15F90 - код 90000 - получаем 0
    3A 41 02 0F 58 - 0x20F58 - код 135000 - получаем 45
    3A 41 02 BF 20 - 0x2BF20 - код 180000 - получаем 90
    3A 41 01 24 94 - 0x12494 - код 74900 - получаем -15.1 (74900/1e3-90=-15.1)
     
    Daniil нравится это.
  18. Daniil

    Daniil Гуру

    В моём "детстве" так оно и было. Я смотрел на свой код и удивлялся каким быдло-кодером я был) Поэтому сейчас можно сделать универсально, правильно... детские травмы:D
    Хотя тут просто if((bt>0)||(i==0)) убрать и вот они фиксированные нули...на вкус и цвет..
     
  19. Belkin

    Belkin Гик

    Я таким образом в 2017-м делал р/у для машинки...
    Пакет посылки из 8 символов:
    AA BB CC DD EE FF GG HH
    AA - кнопка "вперед"
    BB - кнопка "назад"
    CC - кнопка "влево"
    DD - кнопка "вправо"
    EE - кнопка "сигнал"
    FF - кнопка "габариты"
    GG - кнопка "фары"
    HH - регулятор скорости (ШИМ)

    Можно было бы AA...GG передать одним байтом, затем побитно разбирать, но так оказалось более помехоустойчиво, т.к. только HH меняет значение, остальное - или "00" или "FF".
     
    Daniil нравится это.