Передач данных
- Войдите на сайт для отправки комментариев
Вс, 29/10/2017 - 21:09
Здравствуйте необходимо сделать следующее. Есть некоторое количество массивов переменной длины записанных в файлы в некотором виде. На компьютере необходимо из программы на c# передавать в ардуино определенный массив( например, button1 - массив 1 и т.д.). Ардуино должно принять данные, т.е. создать массив необходимой размерности и после приема оповестить компьютер о готовности запустить цикл с задачей данных из этого массива на шим выход, а по окончании цикла также оповестить компьютер.
А в чём, собственно, вопрос? Понял только, что есть данные, и что-то нужно с ними сделать. Проблема в чём у вас? Что не получается из того, что вы уже сделали? И что именно вы уже сделали, прежде чем столкнуться с трудностью?
Здравствуйте необходимо сделать следующее.
Ну, необходимо, так делайте.
Ну у меня получалось несколько вариантов но все кривоватые, вот поэтому и спрашиваю алгоритм последовательности действий.
Уже предвижу следующий ответ Вам:
Алогритм:
Учитесь делать правильно -> Научились? -> Да -> Делаете правильно.
->Нет -> возврат в начало цикла
:)))
Я так понял, таким образом ставить вопрос в этой ветке - гиблое дело. А с таким описание технической задачи - и подавно.
Тут вопрос не только по ардуино если честно но и по клиенту на компьютере, с опрос com porta не очень понятно как грамотно все это организовать. И ещё большой вопрос по поводу analogWrite, как быстро срабатывает эта функция, т.к. мне необходимо устанавливать значения из считанного массива каждые 10 мс
Ну у меня получалось несколько вариантов но все кривоватые,
Варианты в студию с описанием, что именно в них кривовато.
analogWrite порядка 5 микросекунд выполянется. Есть способы ускорения. Но вам они судя по всему не нужны.
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мкс.
Тот же самый скетч на уно 4468 мкс. на 1000 прогонов
А если написать свой блэкджек (просто для тестов)
void analogWritePin6(byte val) { sbi(TCCR0A, COM0A1); OCR0A = val; }получается 504 мкс на 1000 прогонов т.е. пол микросекунды
Возвращаясь к этой теме, вообщем я отправляю с компьютера 2 стартовых байта: допустим 0xFA и 0xAF, затем шлю какую-нибудь команду для проверки связи с ардуино и 2 стоповых байта, на что она должна выдать мне ответ, состоящий из стартовых байт - команды -стоповых байт. После этого опять стартовые байты и массив байтов примерно 1500 элементов, где первый элемент это количество элементов, а остальные данные необходимо разбить на 3 массива одинаковой длины и выдать команду компьютеру что прием окончен. Далее по приходу определенной команды на ноге ардуино в цикле генерируется шим с использованием данных из полученных масивов и после отправляется команда в компьютер о выполнении работы. Собственно вопрос как это все лучше на стороне ардуино реализовать...
Собственно вопрос как это все лучше на стороне ардуино реализовать...
У вас есть признаки начала пакета и окончания пакета. Читаете байты в буфер, прочитали два байта, проверили - это стартовые байты? Если да - ставите флаг, что надо читать до приёма стоповых байт, как только приняли стоповые байты, анализируете, что пришло в теле пакета. Отсылаете обратно, что нужно. И так по кругу.
Излишне усложнено начало передачи. Шлете стартовый STX (а нафига изобретать, все уже придумано), в ответ должен контролер ответить ACK. Все. Дальше длина (2 байта) и данные. Конец приема - по принятию указаной длины. Ну или отвалится по таймауту. После последнего байта данных по хорошему CRC отправляется. Контроллер его проверяет и при успехе отвечает ACK. Если его принял ПК - значить все ОК и контроллер готов.
Вот тут вопрос, как быть если в данных придет то же значение как стоповый бит, что делать? И размер массива в байт не поместится, и до меня сейчас только дошло что весь массив в ОЗУ не влезет...
Ничего не делать. Вы же знаете сколько данных должно быть. Нафига в них стоповые искать какие то, да и какие такие стоповые. Я таких не вижу. Размер массива - любое но фиксированое. Разумно 2 байта брать.
Если в память не влазит - проблема. Может и не разрешимая. А может формат хранения данных поменять и влезет.
Излишне усложнено начало передачи. Шлете стартовый STX (а нафига изобретать, все уже придумано), в ответ должен контролер ответить ACK. Все. Дальше длина (2 байта) и данные. Конец приема - по принятию указаной длины. Ну или отвалится по таймауту. После последнего байта данных по хорошему CRC отправляется. Контроллер его проверяет и при успехе отвечает ACK. Если его принял ПК - значить все ОК и контроллер готов.
Про STX и ACK можно поподробнее и как два байта преобразовать?
http://www.theasciicode.com.ar/ascii-control-characters/start-of-text-as...
Два байта - приняли один, потом второй один из них *256 + второй. Начинает мне казатся, что вашей компетенции недостаточно для реализации задачи. Может подучитесь сразу? Потому как далее пойдет приведение типов, а опыт с# там только в минус идет.
Наверное глупый вопрос но например я объявил массив, далее размер его когда получил, создал уже определенного размера и допустим все считалось все хорошо, а затем передаю размер следующего массива отличающегося от первого и уже получается массив другого размера. Первый массив у меня потрется из памяти?
Да вот необходимо подучится далее задачи намного сложнее будут и уже не на ардуино
Есть разные способы работы с памятю. Возможно соответственно разное. Для начала - этюд там вверху страницы есть, почитайте.
Вы имеете ввиду, например в скетче в начале я создаю массив byte *pwm= new byte[50] ( заполняю его данными по умолчанию), далее если приходит команда на запуск то я использую этот массив, если же приходит команда на загрузку новых данных, тозатем я пишу delete [] pwm и создаю с новым размером?
Только же не так категорично - "забудте про масивы" Изложеной верно, просто массив в куче, т.е. динамический массив. Не создавайте его "в начале". Создавайте когда с ПК прийдет длина данных, вот тогда и создадите нужный.
Только же не так категорично - "забудте про масивы" Изложеной верно, просто массив в куче, т.е. динамический массив. Не создавайте его "в начале". Создавайте когда с ПК прийдет длина данных, вот тогда и создадите нужный.
мне изначально нужно чтобы в памяти уже был по умолчанию ( могу же так сделать или лучше для по умолчанию создать отдельный массив и при приходе команды на запуск проверять если динамический NULL, то использовать по умолчанию, который будет во флеш памяти), а если захочу то нужно другой загрузить... Если по ходу будут какие еще вопросы( если я конечно разберусь что делать с нехваткой памяти) можно я в личку обращусь?
Изначально и много данных - это хранить в PROGMEM надо. И при старте выделить память по размеру и прочитать в неё из PROGMEM. А при поступлении новых данных - освободить ранее выделеную память и выделить заново по размеру новых данных.
Рискну вас запутать, но всеже... всей этой возни с динамической памятю вобщем можна и не делать. Просто обявите максимально большой массив и используйте нужную в текущий момент его часть. Хуже не станет, но проще будет. Вобщем наиболее простой вариант - обявляете большой массив и инитете его часть константами byte M[1500]={1,2,3}; и заводите переменную - текущий размер данніх в массиве word SizeM = 3. Работаете, как с ПК прийдут данные, сохраняете их длину в SizeM и принимаете их в массив затерев старые. Потом дальше работаете. Так и динамическую память не трогаете и с PROGMEM явно не общаетесь )))
Лички тут нет, пишите сюда если чё.
/**/ //-------------------------------------- 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 ) { // } } /**/Я вот запутался, а как лучше мне данные обрабатывать, например так : pwm[i] = (byte)Serial.parseInt(); ( с учетом отправки с компьютера SerialPort.Write(Byte[] buffer, 0, buffer.length) )
Так там другое формирование пакета.https://www.youtube.com/watch?v=Jird6ZLT3Ds
Так там другое формирование пакета.https://www.youtube.com/watch?v=Jird6ZLT3Ds
Теперь я совсем запутался, а причем тут ModBus: у меня три типа команд с компьютера :
1) STX; 0xFF; ETX - проверка Ардуино
3) STX; 0xAF; ETX - Запуск процесса
3) STX; 0xFA; много однобайтовых значений; ETX - проверка Ардуино
Мне необходимо как-то обрабатывать первые два байта и последний, вот теперь не понятно как все это сделать((
Блин после Шарпа так тяжко конечно с Си, а дальше сложнее будет...
Vik648,
Вы уже всех достали! Я Вам ещё неделю назад говорил - выложите то, что Вы сделали, дайте посмотреть-то. Но Вы по-прежнему что-то плетёте про # и думаете, что тут у всех хрустальные шары и все знают, что Вы там нагородили.
Из того, что я пока вижу, а именно
например так : pwm[i] = (byte)Serial.parseInt(); ( с учетом отправки с компьютера SerialPort.Write(Byte[] buffer, 0, buffer.length) )
делаю вывод, что в шарпе Вы разбираетесь точно так же как в нешарпе и на самом деле никаких нескольких вариантов у Вас нет.
Покажите, что Вы сделали, тогда и обсудим, поможем, а так - болтовня одна.
И если вы на своем компютере в среде шарпа не сможете принять данные этой программы, то вам надо идти на форум с шарпом.
/**/ 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() { } /**/Да вы правы я с другими компьютерами не общался, в основном это были прикладные программы для расчетов, анализа данных и т.д. Все что я хотел здесь узнать это сообственно как лучше организовать передачу данных в ардуино и разбор этой информации там, а некоторые "товарищи" в этой теме кроме повышения чувства сообственного величия ничего по делу не предложили...
/**/ 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() { } /**/Это я без проблем могу принять на компьютере...
Это я без проблем могу принять на компьютере...
Ну а дальше все просто если отправите '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(); } } } }это мне понятно
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,.....}.
http://cxem.net/arduino/arduino100.php
http://bigbarrel.ru/arduino_serial_example/
Патаму что дибилы. Им просто нечего предложить па делу!
Вот, ты, например, тебе сказали: выложи свои "несколько вариантов но все кривоватые", чтобы разговор паделу был. Давай, выкладывай! Штоб паделу-то.
Только нечего тебе выкладывать, сбрехал ты про варианты. Вот разговор нипаделу и идёт.
Зачем изобретать велосипед, если есть несколько протоколов обмена и библиотеки к ним?
Выбираешь любую. Все проблемы решены. Просто шлёшь что надо и работаешь не заморачиваясь на детали обмена.