Связь двух Дуино

Злыд
Offline
Зарегистрирован: 19.12.2011

 

Всем привет!

Приобрел Craftduino и Freeduino. Регил их связать, чтобы те выполняли какие-то совместные задачи. Сразу уперся в проблему. 

код передающего МК (передатчик)

#include <SoftwareSerial.h>
SoftwareSerial Serial1(0, 1);

unsigned int x = 0;

void setup(){
   Serial1.begin(9600);
}

void loop(){
  Serial1.println(x);
  x += x == 1000 ? -1000 : 1;
  delay(1000);
}

ежику понятно, что передатчик раз в секунду передает число от 0 до 1000. передает на те же пины, что и обычный Serial

код передающего МК (передатчик)

#include <SoftwareSerial.h> SoftwareSerial Serial1(0, 1); SoftwareSerial Serial2(2, 3); void setup(){   Serial1.begin(9600);   Serial2.begin(9600); } void loop(){   int ib = Serial2.read();   if(ib > 0){     Serial1.print(ib);     Serial1.print(" -> ");     Serial1.write(ib);     Serial1.println(" ");   } }

пин 1 (tx) передатчика подключил к пин 2 (rх) приемника, пин 0 (rx) передатчика к 3 (tx) приемника.

Собственно проблема в том, что на принимающей дуине я получаю мусор, например,

49 -> 1
 3 ->
138 -> ┼

50 -> 2
 3 ->
138 -> ┼

51 -> 3
 3 ->
10 ->

или

52 -> 4
150 -> √
153 -> ≥
133 -> ┘
133 -> ┘ то есть первый байт доходит без изменений, а все последующие как-то изменяются. Сначала подумал, что сдвиг на бит, но и тут оказалось, что ошибся. Подскажите, уважаемые спецы!

 

 

 

Злыд
Offline
Зарегистрирован: 19.12.2011

Админ, а почему нет редактирования сообщения? Криво как-то отпарсилось :( 

Код приемника

#include <SoftwareSerial.h>
SoftwareSerial Serial1(0, 1);
SoftwareSerial Serial2(2, 3);

void setup(){
  Serial1.begin(9600);
  Serial2.begin(9600);
}

void loop(){
  int ib = Serial2.read();
  if(ib > 0){
    Serial1.print(ib);
    Serial1.print(" -> ");
    Serial1.write(ib);
    Serial1.println(" ");
  }
} 

получаемые данные

52 -> 4
150 -> √
153 -> ≥
133 -> ┘
133 -> ┘

 

step962
Offline
Зарегистрирован: 23.05.2011

Злыд пишет:

ежику понятно, что передатчик раз в секунду передает число от 0 до 1000. 

[...]

Собственно проблема в том, что на принимающей дуине я получаю мусор, например,

Никакого мусора там нет - что передаете, то и получаете. Это и ежику должно быть понятно. 

Почитайте о функциях передачи класса Serial (print и println). Задайтесь вопросом, почему разработчик класса ввел в него целых две подобные функции - тоже поймете причины своих неудач.

Злыд
Offline
Зарегистрирован: 19.12.2011

step962 пишет:

Злыд пишет:

ежику понятно, что передатчик раз в секунду передает число от 0 до 1000. 

[...]

Собственно проблема в том, что на принимающей дуине я получаю мусор, например,

Никакого мусора там нет - что передаете, то и получаете. Это и ежику должно быть понятно. 

Почитайте о функциях передачи класса Serial (print и println). Задайтесь вопросом, почему разработчик класса ввел в него целых две подобные функции - тоже поймете причины своих неудач.

 

внимательнее пожалуйста.

отправляю к примеру цифру. к примеру

х = 1;

Serial1.println(x);

 

тому же яжику ясно, что должно прийти три байта "1\r\n" или <49><13><10>, а приходит <49><3><138>

carduino.ru
Offline
Зарегистрирован: 06.12.2011

нужно резистором подтянуть вывод

step962
Offline
Зарегистрирован: 23.05.2011

Злыд пишет:

внимательнее пожалуйста.

Посмотрел повнимательнее. Естественно, не ваш пост - уж больно креативное форматирование там использовано - а класс SoftwareSerial,  а именно метод SoftwareSerial::read():

int SoftwareSerial::read()
{
  int val = 0;
  int bitDelay = _bitPeriod - clockCyclesToMicroseconds(50);
  
  // one byte of serial data (LSB first)
  // ...--\    /--\/--\/--\/--\/--\/--\/--\/--\/--...
  //	 \--/\--/\--/\--/\--/\--/\--/\--/\--/
  //	start  0   1   2   3   4   5   6   7 stop

  while (digitalRead(_receivePin));

  // confirm that this is a real start bit, not line noise
  if (digitalRead(_receivePin) == LOW) {
    // frame start indicated by a falling edge and low start bit
    // jump to the middle of the low start bit
    delayMicroseconds(bitDelay / 2 - clockCyclesToMicroseconds(50));
	
    // offset of the bit in the byte: from 0 (LSB) to 7 (MSB)
    for (int offset = 0; offset < 8; offset++) {
	// jump to middle of next bit
	delayMicroseconds(bitDelay);
	
	// read bit
	val |= digitalRead(_receivePin) << offset;
    }
	
    delayMicroseconds(_bitPeriod);
    
    return val;
  }
  
  return -1;
}

 Шансы считать следующий за первым байт телеграммы у этого метода достаточно призрачные. Это возможно лишь в том случае, если время между очередными вызовами метода меньше паузы между очередными байтами телеграммы. А вы между чтениями очередных байтов отправляете по нескольку байтов через другой Serial-порт. Сколько времени это занимает и каково состояние на RX-пине в тот момент, когда вы наконец снова пытаетесь прочитать символ -  одному микроконтроллеру и автору класса известно.

Так что еще раз повторяю - ищите разницу между Serial.print() и Serial.println() и используйте ее для обеспечения корректного приема пересылаемой информации.

Цитата:

тому же яжику ясно, что должно прийти три байта "1\r\n" или <49><13><10>, а приходит <49><3><138>

Приходит <49><13><10>. Вы неправильно обрабатываете поступающую информацию - не учитываете особенностей используемого класса.

 

ЗЫ: посмотрел метод SoftwareSerial::print(): за пересылаемым байтом выдерживается пауза всего в 1 bitDelay - около 1/10 миллисекунды (при скорости передачи 9600 bps). Только-только принятый байт в буфер записать...

Цитата:

Админ, а почему нет редактирования сообщения? Криво как-то отпарсилось :(

До тех пор, покам на ваш очередной пост никто не ответил, внизу справа доступна кнопка изменить. Пользуйтесь на здоровье.

icms
Offline
Зарегистрирован: 22.03.2011

carduino.ru пишет резистором подтяни :) полностью с ним согласен, а вобще я бы использовал связь по какому либо протоколу типа I2C, помехи и нестабильность при простой передаче по serial будут постоянно доставать. Нужна с связь с проверкой. Либо самому написать что то типа простого протокола связи.