fbpixel
Etiquetas:

Uno de los grandes intereses de la programación es automatizar tareas sencillas. Un buen ejemplo que he encontrado es la modificación de varias líneas de código en un archivo INO para Arduino.

Después de escribir unas docenas de líneas de código en C++ para mi proyecto Arduino, me encontré con un problema de memoria que no podía resolver. Cuando pregunté por ahí, me encontré con la función F() que permite colocar cadenas en la memoria Flash. Esto ahorra mucho espacio cuando se usa mucho Serial.print(). En lugar de modificar el código a mano, escribí un script en python para insertar la función F() en Serial.print().

Descripción del método

En primer lugar, tenemos que abrir el archivo de destino antes de realizar operaciones en él y luego acordarnos de cerrarlo cuando hayamos terminado de utilizarlo.

fileb=open( destfile, "w" )
fileb.close()

Entonces tenemos que recorrer el archivo original línea por línea.

with open(filename) as inofile:
    for line in inofile:
        print(line)

Una vez que es posible navegar por el archivo, detectamos la presencia de «Serial.print» y «Serial.println» en cada línea. Para ello, creamos una función que devolverá la lista de las posiciones de estas cadenas en cada línea.

def find_all_indexes(input_str, search_str):
    l1 = []
    length = len(input_str)
    index = 0
    while index < length:
        i = input_str.find(search_str, index)
        if i == -1:
            return l1
        l1.append(i)
        index = i + 1
    return l1

Para cada línea, si no se detectan las cadenas «Serial.print» y «Serial.println», escribimos la línea en el nuevo archivo tal cual.

if len(indexln)==0 and len(indexl)==0:
			fileb.write(line)

De lo contrario, modificaremos primero las cadenas «Serial.println» y luego las cadenas «Serial.print». Para cada caso, comprobamos que la función F no está ya presente. En este caso, no modificamos la línea y la copiamos en el archivo de destino.

if newl.find('F("')>0:
					pass

En caso contrario, detectamos la posición de los paréntesis y las comillas y luego recuperamos la cadena

j=newl.find('("')
k=newl.find('")')
newlk=newl[j+1:k+1]

Por último, sustituimos la cadena recuperada por la misma cadena insertada en la función F.

print("change String to F()-> "+'Serial.println(F('+newlk+'))')
line=line.replace(newlk,'F('+newlk+')')

Antes de escribir la línea modificada en el archivo de destino.

fileb.write(line)

Aquí tienes un buen ejemplo de cómo aplicar un script de Python para simplificar tu vida. No dudes en comentar si este tutorial te ha sido útil o si encuentras cosas que están mal o que necesitan ser mejoradas.

Código completo

Aquí está el código completo que puedes copiar para probar. Sólo tienes que modificar las direcciones del archivo original (filename) y del archivo de destino (destfile).

#!/usr/bin/python3.4
# -*-coding:Utf-8 -*

def find_all_indexes(input_str, search_str):
    l1 = []
    length = len(input_str)
    index = 0
    while index < length:
        i = input_str.find(search_str, index)
        if i == -1:
            return l1
        l1.append(i)
        index = i + 1
    return l1
    
filename=".\Grab_Parts\Grab_Parts.ino"
destfile=".\Grab_Partsb.ino"



fileb=open( destfile, "w" )
with open(filename) as inofile:  
	#data = file.read() 
	for line in inofile:
		#print(line)
		#print(line.find("Serial.println"))
		indexln=find_all_indexes(line,"Serial.println")
		indexl=find_all_indexes(line,"Serial.print(")
		if len(indexln)==0 and len(indexl)==0:
			fileb.write(line)
		else:
			#change Serial.println
			for i in indexln:
				print("---------------------------------------------------")
				newl=line[i:]
				print(newl)
				if newl.find('F("')>0:
					pass
				else:
					j=newl.find('("')
					k=newl.find('")')
					newlk=newl[j+1:k+1]
					print(newlk)
					if( newlk.find('"')==0):
						print("change String to F()-> "+'Serial.println(F('+newlk+'))')
						line=line.replace(newlk,'F('+newlk+')')
			#print("Result ==> "+line)
			#fileb.write(line)
		
			#change Serial.print after
			indexl=find_all_indexes(line,"Serial.print(")
			for i in indexl:
				print("---------------------------------------------------")
				newl=line[i:]
				print(newl)
				if newl.find('F("')>0:
					pass
				else:
					j=newl.find('("')
					k=newl.find('")')
					newlk=newl[j+1:k+1]
					print(newlk)
					
					if( newlk.find('"')==0):
						print("change String to F()-> "+'Serial.print(F('+newlk+'))')
						#fileb.write('Serial.println(F('+newlk+'))')
						line=line.replace(newlk,'F('+newlk+')')
			print("Result ==> "+line)
			fileb.write(line)
		#print(indexl)
		
fileb.close()

Posibles mejoras

  • Detección automática de archivos INO en un árbol de directorios para modificar todos los archivos de la misma carpeta.

Fuentes