Передач данных

Vik648
Offline
Зарегистрирован: 22.10.2015

Здравствуйте необходимо сделать следующее. Есть некоторое количество массивов переменной длины записанных в файлы в некотором виде. На компьютере необходимо из программы на c# передавать в ардуино определенный массив( например, button1 - массив 1 и т.д.). Ардуино должно принять данные, т.е. создать массив необходимой размерности и после приема оповестить компьютер о готовности запустить цикл с задачей данных из этого массива на  шим выход, а по окончании цикла также оповестить компьютер.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

А в чём, собственно, вопрос? Понял только, что есть данные, и что-то нужно с ними сделать. Проблема в чём у вас? Что не получается из того, что вы уже сделали? И что именно вы уже сделали, прежде чем столкнуться с трудностью?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Vik648 пишет:

Здравствуйте необходимо сделать следующее. 

Ну, необходимо, так делайте.

Vik648
Offline
Зарегистрирован: 22.10.2015

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

5N62V
Offline
Зарегистрирован: 25.02.2016

Уже предвижу следующий ответ Вам:

Алогритм:

Учитесь делать правильно  -> Научились? -> Да -> Делаете правильно. 

                                                                         ->Нет  ->  возврат в начало цикла

:)))

Я так понял, таким образом ставить вопрос в этой ветке - гиблое дело. А с таким описание технической задачи - и подавно.

Vik648
Offline
Зарегистрирован: 22.10.2015

Тут вопрос не только по ардуино если честно но и по клиенту на компьютере, с опрос com porta не очень понятно как грамотно все это организовать. И ещё большой вопрос по поводу analogWrite, как быстро срабатывает эта функция, т.к. мне необходимо устанавливать значения из считанного массива каждые 10 мс

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Vik648 пишет:

Ну у меня получалось несколько вариантов но все кривоватые,

Варианты в студию с описанием, что именно в них кривовато.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

analogWrite порядка 5 микросекунд выполянется. Есть способы ускорения. Но вам они судя по всему не нужны.

5N62V
Offline
Зарегистрирован: 25.02.2016

Penni пишет:

analogWrite порядка 5 микросекунд выполянется. Есть способы ускорения. Но вам они судя по всему не нужны.

проверил на Про-мини кодом



#define PWMPIN 6
#define REVOLUTION 1000
#define VALUE 254

unsigned long time = 0;


void setup() {
  pinMode(PWMPIN, OUTPUT);
Serial.begin(9600);

}

void loop() {
  time = millis();
for (int i = 0; i<REVOLUTION; i++) analogWrite(PWMPIN,VALUE );
 time = millis()-time;
 Serial.print(time);
 while(1);
}

Получилось 7мсек за 1000 раз. 

ПС. Переделал на micros(), получилось 7736мкс.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Тот же самый скетч на уно 4468 мкс. на 1000 прогонов

А если написать свой блэкджек (просто для тестов)

void analogWritePin6(byte val)
{
  sbi(TCCR0A, COM0A1);
  OCR0A = val;
}

получается 504 мкс на 1000 прогонов т.е. пол микросекунды

Vik648
Offline
Зарегистрирован: 22.10.2015

Возвращаясь к этой теме, вообщем я отправляю с компьютера 2 стартовых байта: допустим 0xFA и 0xAF, затем шлю какую-нибудь команду для проверки связи с ардуино и 2 стоповых байта, на что она должна выдать мне ответ, состоящий из стартовых байт - команды -стоповых байт. После этого опять стартовые байты и массив байтов примерно 1500 элементов, где первый элемент это количество элементов, а остальные данные необходимо разбить на 3 массива одинаковой длины и выдать команду компьютеру что прием окончен. Далее по приходу определенной команды на ноге ардуино в цикле генерируется шим с использованием данных из полученных масивов и после отправляется команда в компьютер о выполнении работы. Собственно вопрос как это все лучше на стороне ардуино реализовать...

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Vik648 пишет:

Собственно вопрос как это все лучше на стороне ардуино реализовать...

У вас есть признаки начала пакета и окончания пакета. Читаете байты в буфер, прочитали два байта, проверили - это стартовые байты? Если да - ставите флаг, что надо читать до приёма стоповых байт, как только приняли стоповые байты, анализируете, что пришло в теле пакета. Отсылаете обратно, что нужно. И так по кругу.

Logik
Offline
Зарегистрирован: 05.08.2014

Излишне усложнено начало передачи. Шлете стартовый STX (а нафига изобретать, все уже придумано), в ответ должен контролер ответить ACK.  Все. Дальше длина (2 байта) и данные. Конец приема  - по принятию указаной длины. Ну или отвалится по таймауту. После последнего байта данных по хорошему CRC отправляется. Контроллер его проверяет и при успехе отвечает ACK. Если его принял ПК - значить все ОК и контроллер готов.

Vik648
Offline
Зарегистрирован: 22.10.2015

Вот тут вопрос, как быть если в данных придет то же значение как стоповый бит, что делать? И размер массива в байт не поместится, и до меня сейчас только дошло что весь массив в ОЗУ не влезет...

Logik
Offline
Зарегистрирован: 05.08.2014

Ничего не делать. Вы же знаете сколько данных должно быть. Нафига в них стоповые искать какие то, да и какие такие стоповые. Я таких не вижу. Размер массива - любое но фиксированое. Разумно 2 байта брать.

Если в память не влазит - проблема. Может и не разрешимая. А может формат хранения данных поменять и влезет.

Vik648
Offline
Зарегистрирован: 22.10.2015

Logik пишет:

Излишне усложнено начало передачи. Шлете стартовый STX (а нафига изобретать, все уже придумано), в ответ должен контролер ответить ACK.  Все. Дальше длина (2 байта) и данные. Конец приема  - по принятию указаной длины. Ну или отвалится по таймауту. После последнего байта данных по хорошему CRC отправляется. Контроллер его проверяет и при успехе отвечает ACK. Если его принял ПК - значить все ОК и контроллер готов.


Про STX и ACK можно поподробнее и как два байта преобразовать?

Logik
Offline
Зарегистрирован: 05.08.2014

http://www.theasciicode.com.ar/ascii-control-characters/start-of-text-as...

Два байта - приняли один, потом второй один из них *256 + второй. Начинает мне казатся, что вашей компетенции недостаточно для реализации задачи. Может подучитесь сразу? Потому как далее пойдет приведение типов, а опыт с# там только в минус идет.

Vik648
Offline
Зарегистрирован: 22.10.2015

Наверное глупый вопрос но например я объявил массив, далее размер его когда получил, создал уже определенного размера и допустим все считалось все хорошо, а затем передаю размер следующего массива отличающегося от первого и уже получается массив другого размера. Первый массив у меня потрется из памяти?

Vik648
Offline
Зарегистрирован: 22.10.2015

Да вот необходимо подучится далее задачи намного сложнее будут и уже не на ардуино

Logik
Offline
Зарегистрирован: 05.08.2014

Есть разные способы работы с памятю. Возможно соответственно разное. Для начала - этюд там вверху страницы есть, почитайте. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Vik648 пишет:
Наверное глупый вопрос но например я объявил массив
Забудьте про массивы. В Си если объявили массив, то сразу с размером и навсегда. В Си есть куча - свободная память . Есть указатели. Указатели бывают пустые или указывают от куда начинается данные в памяти.  Начали считывать пакет. Считали размер и по этот размер выдели место в свободной памяти. Вот туда дальше и грузите принимаемые данные. Не нужны данные - вернули освободившую память в кучу и указатель на нее стал пустым.

 

Vik648
Offline
Зарегистрирован: 22.10.2015

qwone пишет:

Vik648 пишет:
Наверное глупый вопрос но например я объявил массив
Забудьте про массивы. В Си если объявили массив, то сразу с размером и навсегда. В Си есть куча - свободная память . Есть указатели. Указатели бывают пустые или указывают от куда начинается данные в памяти.  Начали считывать пакет. Считали размер и по этот размер выдели место в свободной памяти. Вот туда дальше и грузите принимаемые данные. Не нужны данные - вернули освободившую память в кучу и указатель на нее стал пустым.

 

Вы имеете ввиду, например в скетче в начале я создаю массив byte *pwm= new byte[50] ( заполняю его данными по умолчанию), далее если приходит команда на запуск то я использую этот массив, если же приходит команда на загрузку новых данных, тозатем я пишу delete [] pwm и создаю с новым размером?

Logik
Offline
Зарегистрирован: 05.08.2014

Только же  не так категорично - "забудте про масивы" Изложеной верно, просто массив в куче, т.е. динамический массив. Не создавайте его "в начале". Создавайте когда с ПК прийдет длина данных, вот тогда и создадите нужный.

Vik648
Offline
Зарегистрирован: 22.10.2015

Logik пишет:

Только же  не так категорично - "забудте про масивы" Изложеной верно, просто массив в куче, т.е. динамический массив. Не создавайте его "в начале". Создавайте когда с ПК прийдет длина данных, вот тогда и создадите нужный.

мне изначально нужно чтобы в памяти уже был по умолчанию ( могу же так сделать или лучше для по умолчанию создать отдельный массив и при приходе команды на запуск проверять если динамический NULL, то использовать по умолчанию, который будет во флеш памяти), а если захочу то нужно другой загрузить... Если по ходу будут какие еще вопросы( если я конечно разберусь что делать с нехваткой памяти) можно я в личку обращусь?

Logik
Offline
Зарегистрирован: 05.08.2014

Изначально и много данных - это хранить в PROGMEM надо. И при старте выделить память по размеру и прочитать в неё из PROGMEM. А при поступлении новых данных - освободить ранее выделеную память и выделить заново по размеру новых данных. 

Рискну вас запутать, но всеже... всей этой возни с динамической памятю вобщем можна и не делать. Просто обявите максимально большой массив и используйте нужную в текущий момент его часть. Хуже не станет, но проще будет. Вобщем наиболее простой вариант -  обявляете большой массив и инитете его часть константами byte M[1500]={1,2,3}; и заводите переменную - текущий размер данніх в массиве word SizeM = 3. Работаете, как с ПК прийдут данные, сохраняете их длину в SizeM и принимаете их в массив затерев старые. Потом дальше работаете. Так и динамическую память не трогаете и с PROGMEM явно не общаетесь )))

Лички тут нет, пишите сюда если чё.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
//--------------------------------------
class packet_t {
  protected:
    unsigned int len;/*длина*/
    byte *start = NULL;

  public:
    /*конструктоp*/
    packet_t(unsigned int len_ = 0): len(len_) {
      if (len == 0) return;
      start = new byte[len];
    }
    /*деструктор*/
    ~packet_t() {
      if (len == 0) return;
      delete[]  start;
    }
    /*изменить размер*/
    void resize(unsigned int len_) {
      if (len == len_) return;
      len = len_;
      delete[]  start;
      start = new byte[len];
    }
    /*другие методы*/
};
/*прием пакета*/
byte tranferIn(packet_t &pack) {
  return 0;// Ок
}
/*передача пакета*/
byte tranferOut(packet_t &pack) {
  return 0;//Ok
}
//--------------------------------------
//-----main()---------------------------------
packet_t Packet;
void setup() {

}

void loop() {
  packet_t newPack;
  if (tranferIn(newPack) ==0 ) { //

  }
}
/**/

 

Vik648
Offline
Зарегистрирован: 22.10.2015

Я вот запутался, а как лучше мне данные обрабатывать, например так : pwm[i] = (byte)Serial.parseInt(); ( с учетом отправки с компьютера SerialPort.Write(Byte[] buffer, 0, buffer.length) )

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Так там другое формирование пакета.https://www.youtube.com/watch?v=Jird6ZLT3Ds

Vik648
Offline
Зарегистрирован: 22.10.2015

qwone пишет:

Так там другое формирование пакета.https://www.youtube.com/watch?v=Jird6ZLT3Ds

Теперь я совсем запутался, а причем тут ModBus: у меня три типа команд с компьютера :

1) STX; 0xFF; ETX - проверка Ардуино

3) STX; 0xAF; ETX -  Запуск процесса

3) STX; 0xFA; много однобайтовых значений; ETX - проверка Ардуино

Мне необходимо как-то обрабатывать первые два байта и последний, вот теперь не понятно как все это сделать((

Блин после Шарпа так тяжко конечно с Си, а дальше сложнее будет...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Vik648,

Вы уже всех достали! Я Вам ещё неделю назад говорил - выложите то, что Вы сделали, дайте посмотреть-то. Но Вы по-прежнему что-то плетёте про # и думаете, что тут у всех хрустальные шары и все знают, что Вы там нагородили. 

Из того, что я пока вижу, а именно

Vik648 пишет:

например так : pwm[i] = (byte)Serial.parseInt(); ( с учетом отправки с компьютера SerialPort.Write(Byte[] buffer, 0, buffer.length) )

делаю вывод, что в шарпе Вы разбираетесь точно так же как в нешарпе и на самом деле никаких нескольких вариантов у Вас нет.

Покажите, что Вы сделали, тогда и обсудим, поможем, а так - болтовня одна.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Vik648 пишет:
Блин после Шарпа так тяжко конечно с Си, а дальше сложнее будет...
А как вы команды с одного шарпа на одном компьютере в другой шарп на другом компьютере отправляли раньше.  И скорее всего , как сказал ЕвгенийП вы просто этого не делали. От туда и все сложности.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Vik648 пишет:
На компьютере необходимо из программы на c# передавать в ардуино определенный массив( например, button1 - массив 1 и т.д.). Ардуино должно принять данные, т.е. создать массив необходимой размерности и после приема оповестить компьютер о готовности запустить цикл с задачей данных из этого массива на  шим выход, а по окончании цикла также оповестить компьютер.
Если вы хотели это, то то что вы пишете дальше не имеет к этому дело. Есть на Ардуине порт Serial. Вот отсюда и надо плясать.http://arduino.ru/Reference/Serial

И если вы на своем компютере в среде шарпа не сможете принять данные этой программы, то вам надо идти на форум с шарпом.

/**/
int Masiv[10];
void setup() {
  Serial.begin(9600);
  /*загрузим массив некоторыми данными*/
  for (byte i = 0; i < 10; ++i) Masiv[i] = 10+i;
  /* и отправим их в порт*/

  for (byte i = 0; i < 10; ++i) {
    Serial.print(i);
    Serial.print(":");
    Serial.print(Masiv[i]);
    Serial.println();
  }

}

void loop() {
}
/**/

 

Vik648
Offline
Зарегистрирован: 22.10.2015

qwone пишет:

Vik648 пишет:
Блин после Шарпа так тяжко конечно с Си, а дальше сложнее будет...
А как вы команды с одного шарпа на одном компьютере в другой шарп на другом компьютере отправляли раньше.  И скорее всего , как сказал ЕвгенийП вы просто этого не делали. От туда и все сложности.

Да вы правы я с другими компьютерами не общался, в основном это были прикладные программы для расчетов, анализа данных и т.д. Все что я хотел здесь узнать это сообственно как лучше организовать передачу данных в ардуино и разбор этой информации там, а некоторые "товарищи" в этой теме кроме повышения чувства сообственного величия ничего по делу не предложили...

Vik648
Offline
Зарегистрирован: 22.10.2015

qwone пишет:

/**/
int Masiv[10];
void setup() {
  Serial.begin(9600);
  /*загрузим массив некоторыми данными*/
  for (byte i = 0; i < 10; ++i) Masiv[i] = 10+i;
  /* и отправим их в порт*/

  for (byte i = 0; i < 10; ++i) {
    Serial.print(i);
    Serial.print(":");
    Serial.print(Masiv[i]);
    Serial.println();
  }

}

void loop() {
}
/**/

 

Это я без проблем могу принять на компьютере...

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Vik648 пишет:

Это я без проблем могу принять на компьютере...

Ну а дальше все просто если отправите 's' то вам в порт отправится вся информация из массива

/**/
int Masiv[10];
void setup() {
  Serial.begin(9600); // устанавливаем последовательное соединение
  /*загрузим массив некоторыми данными*/
  for (byte i = 0; i < 10; ++i) Masiv[i] = 10 + i;
}

void loop() {
  if (Serial.available() > 0) {  //если есть доступные данные
    // считываем байт
    int incomingByte = Serial.read();
    if (incomingByte == 's') {
      /* и отправим их в порт*/
      for (byte i = 0; i < 10; ++i) {
        Serial.print(i);
        Serial.print(":");
        Serial.print(Masiv[i]);
        Serial.println();
      }
    }
  }
}

 

Vik648
Offline
Зарегистрирован: 22.10.2015

это мне понятно

int n;
int firstElement;
byte *pwmValues;
byte *pwmTimes;
#define CORRECT_FIRST_ELEMENT 9
#define LED_PIN 3


void setup() 
{
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  TCCR2B = TCCR2B & 0b11111000 | 0x01;
}

void loop() 
{

    if(Serial.available() > 0)
     {
        firstElement = Serial.parseInt();
		
        if(firstElement == CORRECT_FIRST_ELEMENT)
        {
          n = Serial.parseInt();
          pwmValues = new byte[n];
		  pwmTimes = new byte[n];
          for(int i = 0; i < n; i++)
          {
            pwmValues[i] = (byte)Serial.parseInt();
			pwmTimes[i] = (byte)Serial.parseInt();
          }
           Serial.clear();
          for(int i = 0; i < n; i++)
          {
            analogWrite(LED_PIN, pwmValues[i]);
            delay(pwmTimes[i]);
          }
          analogWrite(LED_PIN, 0);
        }
        else if (firstElement == 33)
        {
          Serial.write(66);
          Serial.clear();
        }
        
     }
}

Вот такой пример у меня есть, теперь бы хотелось пределать, чтобы с компьютера слался стартовый байт(именно как число, например 0xFF) затем код команды (либо проверка ардуино, либо загрузка данных либо выполнение фрагмента где я задаю ШИМ) и в конце желательно контрольную суммму и стоповый байт. И сами данные соответсвенно например массив Byte[1500]= {0,240,0,240,4,15,10,5,15,10,.....}. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Vik648 пишет:
некоторые "товарищи" в этой теме кроме повышения чувства сообственного величия ничего по делу не предложили...

Патаму что дибилы. Им просто нечего предложить па делу!

Вот, ты, например, тебе сказали: выложи свои "несколько вариантов но все кривоватые", чтобы разговор паделу был. Давай, выкладывай! Штоб паделу-то.

Только нечего тебе выкладывать, сбрехал ты про варианты. Вот разговор нипаделу и идёт.

nik182
Offline
Зарегистрирован: 04.05.2015

Зачем изобретать велосипед, если есть несколько протоколов обмена и библиотеки к ним?
Выбираешь любую. Все проблемы решены. Просто шлёшь что надо и работаешь не заморачиваясь на детали обмена.