BUG en arduino? String=String no se asigna

Hola Llevo varios días atrancado con un problema al cual no le veía solución en mi sistema de alarma vía SMS el trozo de código condensado es

String ESTADO = "";
String CON_LUZ=""; 
.
.
.
ESTADO="PRUEBA";
CON_LUZ=ESTADO;
.
.
.
if (CON_LUZ.length() == 0) .....

Como se puede ver, a ESTADO se le asignan datos. Para preservar lo asignado y controlarlo, al String CON_LUZ se le copia ESTADO íntegramente. Pues bien, el if posterior se cumple. Después de hacer test en otro sketch creado para eso y ver que funcionaba perfectamente, me dispuse a analizar el código (unas 850 lineas) par ver donde y cuando se borraba CON_LUZ. No encontré nada. En ultima instancia puse unas lineas para comprobar que todo estaba correcto y me llevé la sorpresa

//#define CON_MONITOR
    Serial.println("ya hay corriente");
    Serial.println(ESTADO);
    Serial.println(CON_LUZ);
    Serial.println("----------");
    Serial.flush();
//#endif

Dando el siguiente resultado:

ya hay corriente
PRUEBA

----------

Como para compilar y que el arduino uno vaya mas ligero, puse defines para eliminar totalmente los Serial.print, hice la prueba dejando simplemente las lineas de arriba y el resultado fue

ya hay corriente
PRUEBA
PRUEBA
----------

Entonces me llevo a pensar en un bug debido a la memoria para variables globales Estos son los datos de compilación antes (con los Serial incluidos)

El Sketch usa 15048 bytes (46%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 1505 bytes (73%) de la memoria dinámica, dejando 543 bytes para las variables locales. El máximo es 2048 bytes.

y después, donde no hay bug y con los seriales excluidos de la compilación

El Sketch usa 11736 bytes (36%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 804 bytes (39%) de la memoria dinámica, dejando 1244 bytes para las variables locales. El máximo es 2048 bytes.

Quedo a vuestra disposición para hacer las pruebas que se necesiten, pero mi ingles es peor que nulo Saludos

¿La compilación de ese código no te da errores de sintaxis?

:D

Hector_A: ¿La compilación de ese código no te da errores de sintaxis?

:D

NO. ¿Dónde ves el error de sintaxis? Lo que he expuesto es un resumen de lo que ocurre por lo que es posible que haya algún error de tecleo

Por cierto, se me olvidaron 2 lineas en

//#define CON_MONITOR
Serial.println("ya hay corriente");
Serial.println(ESTADO);
Serial.println(CON_LUZ);

CON_LUZ="Prueba 2";         // 1
Serial.println(CON_LUZ);     // 2

Serial.println("----------");
Serial.flush();
//#endif

Y da como resultado

ya hay corriente
PRUEBA

Prueba 2
----------

Saludos

No se puede ver nada porque no publicaste nada, solo lo que tu crees que falla pero para nosotros es imposible entender y probar algo con lo poco que das.

Por eso las normas piden que se postee todo el código @bosoft para evitar estas cosas.

Si el código ocupa mas de 9k lo adjuntas.

Aclaro: no esta dicho de mala manera, simplemente respondo como si estuvieramos cara a cara y yo te dijera.. no te puedo responder porque no puedo leer tu código.

surbyte:
No se puede ver nada porque no publicaste nada, solo lo que tu crees que falla pero para nosotros es imposible entender y probar algo con lo poco que das.

Por eso las normas piden que se postee todo el código @bosoft para evitar estas cosas.

Si el código ocupa mas de 9k lo adjuntas.

Aclaro: no esta dicho de mala manera, simplemente respondo como si estuvieramos cara a cara y yo te dijera… no te puedo responder porque no puedo leer tu código.

Primero el final: Si has entendido que mi respuesta es de mala manera, pido disculpas sinceramente, no era mi intención

Intentaré explicarme para el resto: El código no tiene nada que ver con el BUG detectado. A mi me ha costado días averiguar que se trataba de un BUG y no de un fallo de programación. Lo que falla, con los datos de compilación que adjunto, está bastante claro a mi entender. Creo que cuando arduino no tiene memoria para copiar un String a otro String, simplemente no hace nada. Podría estar averiguando en que momento de memoria ocurre, pero después de varios días peleando para saber porque CON_LUZ no tiene valor, comprenderás que no quiera afinar mas. Pero si queréis que haga mas pruebas, estoy dispuesto.

Si sigues los “trozos” de código que he publicado, te darás cuenta que no es normal lo que ocurre y, mirando los datos de compilación, se puede entender que algo raro pasa. También he dicho que hice otro sketch para comprobar el código que solo tenía una docena de lineas y funcionó correctamente. Ahí es donde empece a pensar en el bug.

Una vez termine la alarma, probaré a simular el error. En caso de pillarlo lo publicaré. Pero no puedo publicar el sketch que estoy haciendo porque me llevaría horas/dias eliminar los datos privados y poner falsos para que mantuviese el mismo tamaño/memoria

Saludos

PD: llevo mas de 25 años programando, primero con C y después C++.

No lo pongo en duda y me di cuenta que sabes programar.
CUando usas String de tanto en tanto pasan estas cosas.

Te recomiendo que uses la rutina freeRAM o freeAvailable que esta en el playground, te permitirá detectar si en algún momento te quedas corto y por eso te esta fallando el programa.

Gracias, lo pruebo e informo

Saludos

Hola surbyte,. Ante todo gracias por tu ayuda He logrado usar la librería MemoryFree y me informó de lo que ya sabía: el UNO está al limite de SRam. Lo que ocurrió fue que la librería, al usar una pequeña cantidad de ram, empeoró la situación.

Veamos: Yo uso 5 Strings, de los cuales 2 son con valor fijo (estoy pensando en cambiarlos a chars) y los otros 3 se escriben y se borran durante la ejecución. Son 2 de estos 3 últimos los que no funcionaban correctamente antes de instalar MemoryFree. Pero Al instalarla se desmadró todo, incluidos los 2 "fijos". Los valores de los 5 Strings eran un caos de basura y mezclas de literales que usaba para mostrar en monitor serie tipo Serial.println("Llamada recibida");

Entonces me decanté por averiguar como podría guardar y usar las cadenas literales de otra forma y encontré el modificador F() para guardarlos en la memoria Flash, que es la que se usa para guardar el programa. La cantidad de memoria disponible para flash en mi UNO es de 32KB, de los cuales usaba alrededor del 36%, veamos los datos anteriores

El Sketch usa 11736 bytes (36%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 804 bytes (39%) de la memoria dinámica, dejando 1244 bytes para las variables locales. El máximo es 2048 bytes.

y los últimos simplemente usando F() en los literales: Serial.println(F("Llamada recibida"));

El Sketch usa 13118 bytes (40%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 513 bytes (25%) de la memoria dinámica, dejando 1535 bytes para las variables locales. El máximo es 2048 bytes.

Como podréis ver, la SRam a mejorado en mas 290 bytes libres, lo cual espero que sea suficiente para que los Strings no me hagan ninguna de las suyas. En cambio la memoria Flash ha usado 1382 bytes mas (un 4%). En teoría esto no debe "molestar" durante la ejecución

Sigo diciendo, que aunque haya poca memoria, la clase String tiene un bug y se desmadra cuando tiene poca memoria para trabajar. Se debería corregir

Ahora me toca hacer todas las pruebas que ya había realizado de nuevo. Espero que sea suficiente

Saludos

Mi respuesta será muy simple. No uso Strings salvo cuando el código es muy simple pero en condiciones como la tuya siempre uso cadenas de chars. Igualmente por tu comentario el uso de F() resolvió todo el problema y que ocupe mas flash no te afecta. Como digo... si no la usas para que sirve?

ArduMyth: Hombre, yo veo los string del autor en mayúsculas cual constantes que por supuesto no afecta en nada al funcionamiento, pero vamos, no he visto yo en las empresas programadores saltándose el estándar básico, por lo que yo no pongo en duda que no sepa lo básico pero son de esas cosas que chirrían, cómo por ejemplo vemos en un código el uso del camel case y a continuación de snake case. Un popurrí de aquí y allá sin seguir una estructura.

Yo concluyo que sin parte del código donde pueda ver el funcionamiento y al menos la longitud asignada a mí el error puede ser X o Y, a saber si hay algo más por medio que no sepamos...

No he entendido nada, porque no creo que estés sugiriendo que la clase String (por llevar mayúscula) es una constante. Lo de los nombres de las variables en mayúsculas lo uso por simple visibilidad si es a lo que te refieres

surbyte: Mi respuesta será muy simple. No uso Strings salvo cuando el código es muy simple pero en condiciones como la tuya siempre uso cadenas de chars. Igualmente por tu comentario el uso de F() resolvió todo el problema y que ocupe mas flash no te afecta. Como digo... si no la usas para que sirve?

Pero cuando se complican los montajes de los string (minúsculas), los String ayudan mucho ya que la programación es mas simple. Pero te estoy haciendo caso y empiezo a cambiar algunos String a char. Por cierto, no tenía ni idea que existía algo como F().

Por falta de tiempo todavía no he podido volver a hacer las pruebas, con lo cual, no se todavía si el modificador F() ha dado resultado

Saludos y muchas gracias por vuestras respuestas

Hola Después de hacer las primeras pruebas, debo decir que el aplicar el modificador F() ha dado resultado Los Strings funcionan sin problemas y el sistema se nota mas veloz. He encontrado errores de programación, que antes parecían aleatorios, y ahora se repiten con total normalidad. Antes podían haber fallos al asignar datos a un String e incluso un String tener datos y el .length() ser 0 y eso volvía loco a cualquiera

Gracias por tu ayuda surbyte, sin haberme aconsejado el MemoryFree no hubiese sido capaz de encontrar la solución. Por cierto, no puedo quitar los 3 últimos Strings, o al menos no se me ocurre como, ya que tampoco se cuanto ocupan u ocuparán los datos recibidos desde la SIM900

Y gracias a todos los que han intentado buscar una solución esto, o al menos lo han pensado, pero no la han encontrado

Saludos

PD: la clase String tiene un BUG trabajando con poca memoria

No los quites porque por tus dichos el programa ya cambió dramáticamente de zona de peligro (ROJA) a zona segura (VERDE) no hay problema en usarlos.

Cuando estas en la zona ROJA con cosas raras y sin la herramienta que todo fan de Arduino necesita que es un debugger no hay mas que apuntarle a los culpables de siempre... los String. Y la herramienta que te sugerí siempre lo señala.

Ahora como tarea para el hogar te queda jugar en las circunstancias críticas como hacer que los Strings se mantengan contenidos sin hacer crecer el consumo de SRAM.

Pero eso para luego que resuelvas tu tarea y siempre y cuando te pique la curiosidad como programador.

Mucho de lo que me motiva en este foro son estas peculiaridades y saber de tips & tricks (trucos y consejos) que los detectan.

X ejemplo: ayer me vi unos videos de un repaador de fuentes de PC y en lugar de usar instrumentos el solo basó toda su explicacion en los ruidos de la fuente ATX.. sencillamente genial. Me puse a revisar fuentes para seguir sus consejos y 95% pude dar con el problema como el lo mencionó. Entonces, eso es lo importante al menos para mi.