Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eliminar delayMicroseconds() #35

Open
peninquen opened this issue Jan 19, 2016 · 7 comments
Open

Eliminar delayMicroseconds() #35

peninquen opened this issue Jan 19, 2016 · 7 comments

Comments

@peninquen
Copy link
Owner

Para hacer más eficiente el código y permitir la ejecución de otros procesos sin retrasos es necesario eliminar delayMicroseconds() que puede introducir una parada en el procesador de hasta 11.458 microsegundos a 2400 bauds.
Ahora está así:

    case SENDING: 
      if ((*_hwSerial).availableForWrite() == SERIAL_TX_BUFFER_SIZE - 1) { //TX buffer empty 
        // time to send last byte and required empty time space 
        delayMicroseconds(_T2_5); 

La función comprueba el buffer TX, cuando está vacio significa que el último byte se encuentra en el registro de TX del UART, por lo que se para hasta asegurar que se ha enviado y además le datos un espacio vacio de T1.5.

Para la nueva función se establece un timer sendMicros y un intervalo sending_interval antes de la función sendBuffer() y en el siguiente estado SENDING realizaría la comparación para cambiar al siguiente estado.
Me preocupa que el UART valla mas deprisa o despacio que, con lo que se pueden presentar dos problemas:

  • Si el UART va más despacio, cambiamos el estado de TxenablePin a LOW antes de tiempo, y se interrumpe la TX.
  • Si el UART va más deprisa de lo esperado, el MAX485 continua en modo Tx y se empiezan a recibir datos.

Voy a hacer pruebas de timing en microsegundos para confirmar, me falta un osciloscopio para analizarlo correctamente.

@peninquen
Copy link
Owner Author

Me contesto yo mismo porque veo la solución más sencilla:

    case SENDING:

      if ((*_hwSerial).availableForWrite() < SERIAL_TX_BUFFER_SIZE - 1) { //TX buffer not empty 
        tMicros = micros();
        return false;
      }
      // time to send last byte and required empty time space 
      if ( micros() - tMicros() <_T2_5 ) return false; 

      // clean RX buffer 
      while ((*_hwSerial).available()) (*_hwSerial).read(); 

      // MAX485 Receiving mode 
      digitalWrite(_TxEnablePin, LOW); 
      _state = RECEIVING; 

      //starts  slave's timeOut 
      _timeoutMillis = millis(); 
      frameSize = 0; 

      return false; 

@cosmopaco
Copy link
Collaborator

Esto no me parece buena idea.
Si el programa principal no hace llamadas cíclicas dentro del tiempo estimado esto no funcionara.

Para llegar a este nivel se tendria que trabajar con interrupciones ya sean por tiempo (puede haber conflictos con otras librerías que utilizan los diferentes timers). Para ser mas preciso se puede trabajar con la interrupciones del periférico UART. Los AVR se pueden configurar para producir una interrupción cuando se ha enviado el ultimo bit, es problemático ya que difieren ligeramente dependiendo del microcontrolador y seria muy complicado portarlo a ESP8266

@cosmopaco
Copy link
Collaborator

Reabro

@cosmopaco cosmopaco reopened this Jan 20, 2016
@peninquen
Copy link
Owner Author

Expongo al detalle como lo veo:

  • He calculado el tiempo entre llamadas a MBSerial.available() cuando no hay otro proceso en 650 us - 800 us (lo he hecho poniendo el monitor serial a 235400 bauds y haciendo una llamada Serial.print(micros())).
  • Desde que availableForWrite() devuelve buffer vacío debemos esperar al menos T1 para asegurar que el último byte ha salido. En ese momento podemo poner TxEnablePin en LOW.
  • El esclavo que inicia la respuesta debe esperar al menos T4.5 ( 1 de enviar y 3.5 de espera).
BAUDRATE 2400 9600 19200
T1 4.583 1.146 573
T1_5 6.875 1.719 859
T3_5 16.042 4.010 2.005
T4_5 20.625 5.156 2.578

No parece razonable plantear baudrate mayores de 19200 con un procesador 328, así que el tiempo disponible para cortar está entre 573 us y 2.578 us. Debido a una posible detección tardía del buffer vacío, planteo el corte a T2.5. Por otro lado, utilizar un delayMicroseconds() de 2 ms me parece un bloqueo alto, que en el caso de transmisiones a 2400 bauds se eleva a 12 ms.

@peninquen
Copy link
Owner Author

En otras librerias como libmodbus se trata este tema y utilizan la función tcdrain()
stephane/libmodbus#208
La función esta definida en librerías linux y unix, sería cuestión de implentarla en hardwareSerial.h del arduino y del ESP8266

@peninquen
Copy link
Owner Author

Existe una diferencia importante entre Arduino y el ESP8266 con respecto a delay() y delayMicroseconds()
https://github.com/esp8266/Arduino/blob/master/doc/reference.md#timing-and-delays
El ESP necesita delay() para procesar WifFi. Estoy mirando otra funcion que menciona, yield() equivalente a delay(0) pero que permite desatascar los procesos pendientes del WiFi.

@helianto
Copy link

En el caso del esp8266 no me complicaria mucho la vida, mas que nada porque
dado el dispositivo y el uso tipo que se le va a dar, lo mas probable es
que no incorpore ningun otro dispositivo adicional (sensor), por lo que
tener paradas en el microprocesador no es un problema. Si a esto le
añadimos que el uso mas probable es el envio a bases de datos remotas,
muchas de las cuales tienen limitaciones en el numero de envios por minuto,
tenemos que un retardo de 1 segundo en la lectura no es ningun problema
(retardo que, por cierto tambien tenemos si queremos leer temperaturas con
sondas digitales).

Pero en cualquier caso... tu decides

El 24 de enero de 2016, 20:25, Jaime García notifications@github.com
escribió:

Existe una diferencia importante entre Arduino y el ESP8266 con respecto a
delay() y delayMicroseconds()

https://github.com/esp8266/Arduino/blob/master/doc/reference.md#timing-and-delays
El ESP necesita delay() para procesar WifFi. Estoy mirando otra funcion
que menciona, yield() equivalente a delay(0) pero que permite desatascar
los procesos pendientes del WiFi.


Reply to this email directly or view it on GitHub
#35 (comment)
.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants