Comunicación en serie de larga distancia (y creo que de baja frecuencia) con Arduino [cerrado]

0

Necesito implementar una comunicación de larga distancia (hasta 15 kilómetros) entre algunos dispositivos electrónicos. Los dispositivos son algunos tableros en chips AVR con la biblioteca Arduino y una Raspberry pi como el mainframe para mostrar datos adquiridos. Standarts que conozco no soporta distancias tan largas. Por ejemplo, RS-485 solo se puede utilizar hasta 1200 metros.

Soy consciente de que los arroces de distancia permitidos disminuyen la velocidad de transferencia de datos y no tengo reclamos por el tiempo de transferencia. 1 byte por 1, 10 o 20 segundos funcionará bien. Por lo tanto, se consideró escribir una función personalizada para comunicarse a una velocidad muy baja. También tengo una pregunta, ¿puede haber una biblioteca fácilmente disponible para este problema?

He encontrado la implementación en serie del software simple para Arduino en la web. Consta de dos funciones: lectura y escritura y la constante de tiempo. Lo utilicé con algunas correcciones, y funcionó con una placa ATTiny personalizada como transmisor y arduino como receptor. Cuando hice un tablero receptor personalizado con ATMega1284P, aparecieron los errores. Algunos de ellos fueron arreglados por mí. El estado actual de las cosas es extraño, algunos canales funcionan y otros no.

El código del transmisor:

void sendCode(int pin, int data)
{
  // startbit
  digitalWrite(pin, LOW);
  delayMicroseconds(ONE_BIT_TIMING);

  byte mask;
  for (mask = 0x01; mask > 0; mask <<= 1) {
    if (data & mask) { // choose bit
       digitalWrite(pin, HIGH); // send 1
    }
    else {
       digitalWrite(pin, LOW); // send 0
    }
    delayMicroseconds(ONE_BIT_TIMING);
  }
  //stop bit
  digitalWrite(pin, HIGH);
  // pause between packages
  delayMicroseconds(ONE_BIT_TIMING * 10);
}

void loop() {
  sendCode(GND_SIG_PIN, GND_SIG_CODE);
  sendCode(BROWN_PIN, BROWN_CODE);
  sendCode(BLUE_PIN, BLUE_CODE);
  sendCode(BLACK_PIN, BLACK_CODE);
  sendCode(WHITE_PIN, WHITE_CODE);
  sendCode(GREEN_PIN, GREEN_CODE);
  sendCode(RED_PIN, RED_CODE);
  sendCode(GND_INT_PIN, GND_INT_CODE);
  sendCode(RED_INT_PIN, RED_INT_CODE);
  sendCode(BLACK_INT_PIN, BLACK_INT_CODE);
  sendCode(WHITE_INT_PIN, WHITE_INT_CODE);
  sendCode(GREEN_INT_PIN, GREEN_INT_CODE);
}

Funciona bien y emite una señal exactamente como yo quiero.

El código del receptor:

int SWread(int pin)
{
  byte val = 0;
  //wait for start bit
  while (digitalRead(pin));
  if (digitalRead(pin) == LOW) {

    delayMicroseconds(ONE_BIT_TIMING);
    for (int offset = 0; offset < 8; offset++) {
      // Get 100 pin states during the one bit period
      // and write the most common to the variable
      int highCount = 0;
      int lowCount = 0;
      for (int c = ONE_BIT_TIMING; c > 0;) {
        if (digitalRead(pin)) {
          highCount++;
        } else {
          lowCount++;
        }
        c = c - (ONE_BIT_TIMING / 100);
        delayMicroseconds(ONE_BIT_TIMING / 100);
      }
      if (highCount > lowCount) {
        val |= 1 << offset;
      }
    }
    return val;
  }
}

// turn on one led if recieved the expected code and the other if not
void swithLed(int sigPin, int code, int okPin, int failPin) {
  int val = SWread(sigPin);
  if (val == code) {
    digitalWrite(okPin, HIGH);
    digitalWrite(failPin, LOW);
  } else {
    digitalWrite(okPin, LOW);
    digitalWrite(failPin, HIGH);
  }
}

void loop() {
  swithLed(GND_SIG_PIN, GND_SIG_CODE, GND_SIG_OK, GND_SIG_FAIL);
  swithLed(BROWN_PIN, BROWN_CODE, BROWN_OK, BROWN_FAIL);
  swithLed(BLUE_PIN, BLUE_CODE, BLUE_OK, BLUE_FAIL);
  swithLed(BLACK_PIN, BLACK_CODE, BLACK_OK, BLACK_FAIL);
  swithLed(WHITE_PIN, WHITE_CODE, WHITE_OK, WHITE_FAIL);
  swithLed(GREEN_PIN, GREEN_CODE, GREEN_OK, GREEN_FAIL);
  swithLed(RED_PIN, RED_CODE, RED_OK, RED_FAIL);
  swithLed(GND_INT_PIN, GND_INT_CODE, GND_INT_OK, GND_INT_FAIL);
  swithLed(RED_INT_PIN, RED_INT_CODE, RED_INT_OK, RED_INT_FAIL);
  swithLed(BLACK_INT_PIN, BLACK_INT_CODE, BLACK_INT_OK, BLACK_INT_FAIL);
  swithLed(WHITE_INT_PIN, WHITE_INT_CODE, WHITE_INT_OK, WHITE_INT_FAIL);
  swithLed(GREEN_INT_PIN, GREEN_INT_CODE, GREEN_INT_OK, GREEN_INT_FAIL);
}

Los dos últimos canales siempre reciben el código incorrecto, mientras que el otro recibe el correcto y funciona como se esperaba.

    
pregunta Minatko

2 respuestas

1

Como han señalado otros, se está abordando el problema desde el lado equivocado. Si su principal limitación de diseño es la confiabilidad, debe tener en cuenta muchos más aspectos.

Aunque es cierto que velocidades de datos más lentas permitirían comunicaciones más confiables, otros requisitos para la capa física podrían imponer restricciones adicionales que establezcan la velocidad de transmisión más baja deseable. Con una velocidad de datos lenta, obtendrá comunicaciones más confiables con un flujo de bits algo más rápido, altamente redundante y con corrección de errores, que con una velocidad equivalente de baja velocidad.

Una línea de 15 km tendrá interacciones con el entorno circundante de manera muy predecible. Si se coloca de alguna manera a lo largo de líneas eléctricas de 60Hz / 50Hz, actuará como el secundario de un transformador (y una placa de un condensador) en el que se inducirán altos voltajes en modo común . Si una luz incide en algo cerca de esa línea (sin mencionar la línea en sí), habrá pulsos de alta corriente, alto voltaje y alta energía. Para hacer frente a esto necesita aislamiento y protección contra sobretensiones. Estas no son una consideración importante para las líneas de corta distancia, pero aún están presentes.

Por ejemplo. Ethernet, que está diseñada para funcionar solo dentro de edificios y para distancias mucho más cortas, tiene una especificación de 2.5 kV de aislamiento requerido del dispositivo. Y los dispositivos Ethernet explotados por ataques de iluminación cercanos no son tan raros.

Aunque es posible lograr el aislamiento con las comunicaciones de banda base, esto requerirá fuentes de alimentación aisladas y otros elementos que deban colocarse a través de la barrera de aislamiento, lo que hace que sea más probable que se rompa esta barrera y, por lo tanto, menos confiable. El método más simple y confiable para proporcionar aislamiento es el acoplamiento AC a través de un transformador de núcleo toroidal, lo que permite una gran brecha entre los devanados primario y secundario que puede sostener decenas de kV. Sin embargo, el acoplamiento de CA elimina la posibilidad de comunicaciones de banda base. Y, para mantener el transformador a un tamaño razonable, las frecuencias más altas se vuelven deseables. Esto también le permite mantenerse alejado de la gran interferencia de 50/60 Hz que estará presente en una línea tan larga.

Para permitir un cableado no terminado y sin emparejar, debe limitar su frecuencia máxima de portadora para evitar tratar con reflexiones y una atenuación excesiva. Para una línea de 15 km probablemente no quiera ir mucho más alto que 2kHz. Esto lo coloca dentro del territorio de módem de audio de baja frecuencia estándar. Pero aquí hay otro compromiso: los núcleos toroidales para esas frecuencias serán difíciles de conseguir o extremadamente grandes, por lo que podría ser necesario un transformador más común y menos aislado a menos que sea inteligente con el diseño.

Como los módems del teléfono, el IC podría haberse convertido en una rareza (especialmente de la variedad 300baud o 1200baud) y si un protocolo existente como el Protocolo de Transducto Remoto Dirigible en Autopistas (HART), que fue diseñado para restricciones similares, no funciona para usted . En estas frecuencias es bastante fácil diseñar su propio módem de software utilizando ASK o FSK. Eche un vistazo a las computadoras antiguas que solían almacenar datos en cintas de casete (la Apple II tenía un código muy eficiente que se ejecuta en > 5kBaud usando símbolos RS232 sobre FSK).

Necesitarás algunos circuitos analógicos para filtrar el canal y recibir la señal analógica, pero no es nada que no pueda combinarse con algunos pasivos, un op-amp y un disparador de Schmidt.

Si las comunicaciones bidireccionales son necesarias, surgirán problemas adicionales.

    
respondido por el Edgar Brown
-1

Si estás atascado en una banda base, podrías hacerlo de manera similar a como lo hizo Sam Morse en 1844. Envió el mensaje "QUÉ HA LLEVADO A DIOS" en más de 70 km utilizando el Código Morse. Una implementación más moderna podría ser usar un relé de estado sólido como su "clave" de telégrafo impulsada por su arduino que actúa como la "mano" que opera la clave. Los relés y módulos de entrada ópticamente aislados comercialmente disponibles ofrecerían cierta protección a los módulos de CPU sensibles en ambos extremos. Una biblioteca de código Morse para cada cpu evitaría que tuvieras que aprender el código.

Dibujé cómo podría ser una implementación simple. Implica comunicación bidireccional; Volver a transmitir lo que se recibió, aunque no es muy eficiente, sería una buena manera de asegurar la exactitud del mensaje. La resistencia del cable de la transmisión debería ser dimensionada para garantizar que la caída no supere el umbral mínimo del módulo de entrada.

    
respondido por el AlmostDone

Lea otras preguntas en las etiquetas