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.