проблема с массивами

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015
Есть код в котором в цикле успешно заполняется массив  uint8_t outbuf[3]. После записи трех значений он перезаписывается. И так 35 циклов. 
Я успешно вывожу 35х3 = 105 значений в монитор. ВСЕГДА имеем только 105 значений, просто привел упрощенный код.
Теперь, после каждой тройки значений, я перезаписываю эти 3 значения в другой массив. И при выводе в монитор
уже баги... зависание и т.п.
Предположения: 1) outbuf - это типа буфера, который сам очищается при чтении его. 2) нужно применить указатель, а не индекс.  3) тип данных неверный. 
 
int sm = 0;
int sm1 = 1;
int sm2 = 2;
 
int arr1[105];
 
 
void setup() {
  // put your setup code here, to run once:
}
 
void loop() {
  if ( кнопка нажата, то очищаем sm = 0 и далее по коду)
  {
    uint8_t outbuf[3];
    uint8_t rc = Midi.extractSysExData(p, outbuf);  // тут успешно читается поток данных
 
    Serial.print(outbuf[0]); // тут успешно выводим 105 байт данных, 35 строки по 3 байта
    Serial.print(outbuf[1]);
    Serial.print(outbuf[2]);
 
    // ДАЛЕЕ если сделаем перезапись вот так, то.... число выводимых строк уже не 105, а другое... зависание программы и т.п.
    arr1[sm] = outbuf[0];  // каждую тройку перезаписываем в буфер.... сначала в 0,1,2
    arr1[sm1] = outbuf[1];
    arr1[sm2] = outbuf[2];
 
    sm = sm + 3; // стало  3, 4, 5.... потом 6, 7, 8 и т.п. до 105
    sm1 = sm + 1;
    sm2 = sm + 2;
  }
}

 

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017
for (uint8_t i=0; i<3; i++)   arr1[sm+i] = outbuf[i];  // каждую тройку перезаписываем в буфер.... сначала в 0,1,2
 
sm += 3; // стало  3, 4, 5.... потом 6, 7, 8 и т.п. до 105

if (sm>104) sm=0;
 

 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Какие интересные предположения. Таких я тут ещё не встречал.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

DetSimen пишет:

for (uint8_t i=0; i<3; i++)   arr1[sm+i] = outbuf[i];  // каждую тройку перезаписываем в буфер.... сначала в 0,1,2
 
sm += 3; // стало  3, 4, 5.... потом 6, 7, 8 и т.п. до 105

if (sm>104) sm=0;
 

да там больше 105 ничего и нет... А обнуление sm я привел как инициация каждой процедуры чтения.  Что -то другое нужно делать((

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

sadman41 пишет:

Какие интересные предположения. Таких я тут ещё не встречал.

Вам все плохо))) Ничего сам не предлагаешь - "почему мозгами не думаешь?"... Что -то предлагаешь - тоже плохо, зачем ахинею несешь)) Лучше бы что-то конструктивное подсказали, чем флудить))

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

 А обнуление sm я привел как инициация каждой процедуры чтения. 

у вас нет обнуления sm в коде

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

Лучше бы что-то конструктивное подсказали, чем флудить))

Так уже подсказали. возьмите код DetSimena и попробуйте - уверен, что все глюки исчезнут.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Хорошо, я проверю. Спс и отпишусь.

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

Хорошо, я проверю. Спс и отпишусь.

что там проверять-то? так не видите, что у вас sm не обнуляется?

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

dim3740 пишет:

да там больше 105 ничего и нет... А обнуление sm я привел как инициация каждой процедуры чтения.  Что -то другое нужно делать((

???? о_О !!!!

Жертва коррекционной педагогики? ;)))

Просто сделай так, как написал Дед.

------------------------

Может и правда идиот? Но я все-таки поясню, что В ЯЗЫКЕ Си НЕТ ПРОВЕРКИ ИНДЕКСОВ МАССИВА!!!

Поэтому никто не знает, есть ли "там что-то больше 105", так стало яснее?

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

b707 пишет:

dim3740 пишет:

Хорошо, я проверю. Спс и отпишусь.

что там проверять-то? так не видите, что у вас sm не обнуляется?

Понимаете, ведь там читается НЕ непрерывный поток, а максимум - 105 байт данных. Их в МИДИ посылке больше и нет. Я выводил в монитор sm, и он никогда не было больше 105. Процедура делается при каждом нажатии кнопки, и я там sm очищается. 

Может быть arr cделать локальным? Или заранее объявить /присвоить нули? Или не ставить размерность?

Я никогда не работал с массивами. 

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

dim3740 пишет:

Понимаете, ведь там читается НЕ непрерывный поток, а максимум - 105 байт данных. Их в МИДИ посылке больше и нет.

еще раз: откуда программа это знает? Есть признак конца данных?

Давай ты выведешь sm на печать  после 29-ой строки и всё увидишь сам.

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

Процедура делается при каждом нажатии кнопки, и я там sm очищается.

укажите конкретную строчку в своем коде . где sm очищается? - в коде этого НЕТ!

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

это у него кусок особо секретного кода. Где p описан - тоже непонятно.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Спасибо что пытаетесь помочь... думаю, я выложу полный код счас... Но если коротко - то есть обработчик кнопки. В нем запрос за инициализацию обмена. А также сброс sm. В обмене идет только 105 байт. Больше слейв устройство НЕ генерит. Естественно, я получаю их и вывожу на монитор. Успешно! Задача - запомнить эти 105 байт. Все.

 

СТРОКА 116

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015


#include <MIDI.h>
#include <usbh_midi.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif

//Arduino MIDI library v4.2 compatibility
#ifdef MIDI_CREATE_DEFAULT_INSTANCE
MIDI_CREATE_DEFAULT_INSTANCE();
#endif
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif

//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////

USB Usb;
USBH_MIDI Midi(&Usb);

void MIDI_poll();
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);

//If you want handle System Exclusive message, enable this #define otherwise comment out it.
#define USBH_MIDI_SYSEX_ENABLE

#ifdef USBH_MIDI_SYSEX_ENABLE
//SysEx:
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
  Midi.SendSysEx(sysexmsg, sizeofsysex);
}
#endif

void setup()
{
  MIDI.begin(MIDI_CHANNEL_OMNI);
#ifdef USBH_MIDI_SYSEX_ENABLE
  MIDI.setHandleSystemExclusive(handle_sysex);
#endif
  if (Usb.Init() == -1) {
    while (1); //halt
  }//if (Usb.Init() == -1...
  delay( 200 );
}

void loop()
{
  uint32_t t1;
  uint8_t msg[4];

  Usb.Task();
  t1 = micros();
  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
  {
    MIDI_poll();
    if (MIDI.read()) {
      msg[0] = MIDI.getType();
      switch (msg[0]) {
        case midi::ActiveSensing :
          break;
        case midi::SystemExclusive :
          //SysEx is handled by event.
          break;
        default :
          msg[1] = MIDI.getData1();
          msg[2] = MIDI.getData2();
          Midi.SendData(msg, 0);
          break;
      }
    }
  }
  //delay(1ms)
  doDelay(t1, (uint32_t)micros(), 1000);
}

// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
  uint8_t size;
#ifdef USBH_MIDI_SYSEX_ENABLE
  uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
  uint8_t rcode = 0;     //return code
  uint16_t  rcvd;
  uint8_t   readPtr = 0;

  rcode = Midi.RecvData( &rcvd, recvBuf);

  //data check
  if (rcode != 0) return;
  if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
    return ;
  }

  uint8_t *p = recvBuf;
  while (readPtr < MIDI_EVENT_PACKET_SIZE)  {
    if (*p == 0 && *(p + 1) == 0) break; //data end

    uint8_t outbuf[3];
    uint8_t rc = Midi.extractSysExData(p, outbuf);
    if ( rc == 0 ) {
      p++;
      size = Midi.lookupMsgSize(*p);
      _MIDI_SERIAL_PORT.write(p, size);
      p += 3;
    } else {
      _MIDI_SERIAL_PORT.write(outbuf, rc); 
    }
    readPtr += 4;
  }
#else
  uint8_t outBuf[3];
  do {
    if ( (size = Midi.RecvData(outBuf)) > 0 ) {
      //MIDI Output
      _MIDI_SERIAL_PORT.write(outBuf, size);
    }
  } while (size > 0);
#endif
}

// Delay time (max 16383 us)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
  uint32_t t3;

  if ( t1 > t2 ) {
    t3 = (0xFFFFFFFF - t1 + t2);
  } else {
    t3 = t2 - t1;
  }

  if ( t3 < delayTime ) {
    delayMicroseconds(delayTime - t3);
  }
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 - вы издеваетесь? это же не ваш код. Выкладывайте не то, что вы нашли в инете. а то, как вы этот код пытались переделать

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

#include "sav_button.h"

SButton bBank(15, 50, 2000, 0, 0);  // верх справа - банк, а свет 14

int ch;

int sm = 0;
int sm1 = 1;
int sm2 = 2;

int arr1[105];


USB Usb;
USBH_MIDI Midi(&Usb);

void MIDI_poll();  // ЧТО ЭТО ОЗНАЧАЕТ?

void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
  Midi.SendSysEx(sysexmsg, sizeofsysex);
}

​void setup()
{
  ch = 1;
  Serial.begin(9600);
   
  if (Usb.Init() == -1) while (1);
 }

void loop()
{
  Usb.Task();
  Read5in();
  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )  MIDI_poll();
}

void MIDI_poll()
{
  uint8_t size;
  uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
  uint8_t rcode = 0;     //return code
  uint16_t  rcvd;
  uint8_t   readPtr = 0;

  rcode = Midi.RecvData( &rcvd, recvBuf);
  if (rcode != 0) return;
  if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) return ; 
  uint8_t *p = recvBuf;
  while (readPtr < MIDI_EVENT_PACKET_SIZE)
  {
    if (*p == 0 && *(p + 1) == 0) break; //data end

    uint8_t outbuf[3];
    uint8_t rc = Midi.extractSysExData(p, outbuf);
    if ( rc == 0 )
    {
      p++;
      size = Midi.lookupMsgSize(*p);
      Serial.write(p, size);
      p += 3;
    }
    else
    {
      //    Serial.write(outbuf, rc);  //  Мне это не нужно, а нужно запомнить в массив

      Serial.print("ном ");
      Serial.print(ch);
      Serial.print("     ");

      ch++;

      Serial.print(outbuf[0], HEX);
      Serial.print(" ");
      Serial.print(outbuf[1], HEX);
      Serial.print(" ");
      Serial.print(outbuf[2], HEX);
      Serial.print('\n');

      Serial.print("sm ");
      Serial.print(sm);
      Serial.print('\n');

      arr1[sm] = outbuf[0];    
      arr1[sm1] = outbuf[1];
      arr1[sm2] = outbuf[2];

      Serial.print("записано в массив  ");

      Serial.print(arr1[sm], HEX);
      Serial.print(" ");
      Serial.print(arr1[sm1], HEX);
      Serial.print(" ");
      Serial.print(arr1[sm2], HEX);
      Serial.print('\n');

      sm = sm + 3;
      sm1 = sm + 1;
      sm2 = sm + 2;

      p += 4;
    }
    readPtr += 4;
  }
}


void Read5in() {  // обработка кнопки 

  int8_t zapros[] = {0xf0, 0xf7}; // текущий
  
  switch ( b1.Loop() )
  {
    case SB_CLICK:
    
      Midi.SendSysEx(zapros, sizeof(zapros), 0);

      sm = 0;
      break;

  }
}

 

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Ок. Я выложил свой код, который есть упрощенный из библы. Мне там не нужны многие функции. Но я мог по незнанию удалить и что было нельзя. Меня устроит и код библы - он еще выше, только ВСТАВЬТЕ плз запоминание полученных байтов в некий массив. 

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Давайте так... На вид ИМХО код рабочий, потому что НЕ МОЙ, и главное - он работает. Косяк только со стр 18 второй части, но она безобидная. Подскажите, для эксперимента, как переобозвать массив ARR[] , куда его еще попытаться расположить, локально, как инициализировать и т.п.  Мб. Мб обращаться по указателю... Код DetSimen - это просто оптимизация, я его вставлю, но это не решение, мне кажется...  К сожалению, вы не сможете прогнать код, т.к. нужно реальное железо.

Может конфликт в названиях переменных с зарезервированными в библах - они очень тяжелые(((

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

я - пас.

 

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

DetSimen пишет:

я - пас.

Я признателен за все, хоть что-то попробовать еще))) Может этот участок в неком прервании обрабатывается? Что означает на строке 20 перед сетапом..  void MidiPool()? 

Еще есть суждение, что якобы по ЮСБ идут байты не только до 127, как по МИДИ, а до 256. Вызывается переполнение, и чтобы данные все же корректно шли, добавляются лишние байты. Т.е. уже не 105, а может и больше. Я их читаю МИДИ устройством, железным, и оно возможно ОБРАТНО переводит все и говорит, что принято 105. 

Но код же учитывает что может быть иная длина пакета...

 

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

dim3740 пишет:

Что означает на строке 20 перед сетапом..  void MidiPool()? 

Это декларация функции.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

BOOM пишет:

dim3740 пишет:

Что означает на строке 20 перед сетапом..  void MidiPool()? 

Это декларация функции.

Так, а функция должна что-то возвращать)) (А вот обработчик кнопки - не должен).  Мб поэтому и нельзя просто так из этой функции ничего в глобальные переменные записать??? 

Т.е. в монитор можно выводить, а записывать нельзя. Так? Как в САМОЙ функции что-то сбуферировать? И уже потом как-то передавать "наружу"... будем решать. 

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

ты, родное сердце, везде свои sm1 и sm2 замени на (sm+1) и (sm+2). Они читать станет приятнее и ошибка возможно исчезнет! ;)))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

dim3740 пишет:

Так, а функция должна что-то возвращать))

В корне не верное утверждение.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

sm1 и sm2 заменю... понимаю, что у многих это как бельмо на глазу....  Итак, мнение профессионалов: на вскидку все должно работать. Так? Смотреть железо? Кабели, задержки? Действительно, баг не стабильный, но закономерности не могу обнаружить. Что выложить?Скрины монитора нужны? 

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

dim3740 пишет:

Мб поэтому и нельзя просто так из этой функции ничего в глобальные переменные записать??? 

...

Т.е. в монитор можно выводить, а записывать нельзя. Так?

Пожалуйста, не строй догадки! Ты пишешь такую дичь, что желание помогать может пропасть. Не нужно никакого самолечения, доктора - помогут, только не придумывай глупостей.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

dim3740 пишет:

 Итак, мнение профессионалов: на вскидку все должно работать. Так?

Опять догадки?

Нет, не должно. Ты пишешь в занаятую память. Замени sm1 sm2. Для начала, потом поставим ограничитель. Ты делай, а не суетись.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

А ведь все нормально стало!)) после замены/ убрал sm1 sm2. На пару десятков нажатий бага нет. Не совпадение???

Огромное спасибо, а я уж не знал что и думать... Если выползет снова  - отпишусь.... Спасибо))

Вот так проверяю... и ОБА значения равные))

Serial.print(outbuf[0], HEX);
      Serial.print(" ");
      Serial.print(outbuf[1], HEX);
      Serial.print(" ");
      Serial.print(outbuf[2], HEX);
      Serial.print("          ");
      Serial.print('\n');

      for (uint8_t i = 0; i < 3; i++)
      {
        arr1[sm + i] = outbuf[i]; 
        Serial.print(arr1[sm+i], HEX);
        Serial.print(" ");
      }

      sm += 3;

 

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

Serial.print(outbuf[0], HEX);
      Serial.print(" ");
      Serial.print(outbuf[1], HEX);
      Serial.print(" ");
      Serial.print(outbuf[2], HEX);
      Serial.print("          ");
      Serial.print('\n');

      for (uint8_t i = 0; i < 3; i++)
      {
        arr1[sm + i] = outbuf[i]; 
        Serial.print(arr1[sm+i], HEX);
        Serial.print(" ");
      }

      sm += 3;

 

учитесь еще правильно польховаться инкрементами. Зачем делать три сложения, когда можно обойтись одним?

Serial.print(outbuf[0], HEX);
      Serial.print(" ");
      Serial.print(outbuf[1], HEX);
      Serial.print(" ");
      Serial.print(outbuf[2], HEX);
      Serial.print("          ");
      Serial.print('\n');

      for (uint8_t i = 0; i < 3; i++)
      {
        arr1[sm] = outbuf[i]; 
        Serial.print(arr1[sm++], HEX);
        Serial.print(" ");
      }

      //sm += 3; // теперь эта строка лишняя

 

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015
int8_t zapros[] = {0xf0,  0xf7};  
Midi.SendSysEx(zapros, sizeof(zapros), 0);   - это делает

int arr1[105];  ... потом он заполнен
Midi.SendSysEx(arr1, sizeof(arr1), 0);  -- уже не компилируется

ПОЧЕМУ?

 

b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

int8_t zapros[] = {0xf0,  0xf7};  
Midi.SendSysEx(zapros, sizeof(zapros), 0);   - это делает

int arr1[105];  ... потом он заполнен
Midi.SendSysEx(arr1, sizeof(arr1), 0);  -- уже не компилируется

ПОЧЕМУ?

 

ну так компилятор же не просто так "не компилирует", он пишет ошибку. Смотрите сообщения компилятора. Хотите задать вопрос - выкладывайте сообщение компилятора сюда

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015
Тип данных?
 
 
exit status 1
no matching function for call to 'USBH_MIDI::SendSysEx(int [105], unsigned int, int)'
 
Я понимаете могу фугу Баха сыграть, а вот проф программировать надо еще учиться...
b707
Онлайн
Зарегистрирован: 26.05.2017

dim3740 пишет:

Тип данных?
 
похоже что да.
Обратите внимание, что у вас первый массив типа uint8_t. а второй - int. что означает int16_t
Зачем вам массив из int. если у вас содерджимое - байты?