Étiquettes :

Un des gros intérêts de la programmation est d’automatiser des tâches simples. Un bon exemple que j’ai rencontré est la modification de plusieurs lignes de code dans un fichier INO pour Arduino.

Après avoir écrit quelques dizaines de lignes de code en C++ pour mon projet Arduino, je me suis retrouvé avec un problème de mémoire que je n’arrivais pas à résoudre. En me renseignant, je suis tombé sur la fonction F() qui permet de placer les chaines de caractères dans la mémoire Flash. Cela permet de gagner beaucoup de place lorsqu’on utilise beaucoup de Serial.print(). Plutôt que de modifier le code à la main, j’ai écrit un script python permettant d’insérer la fonction F() dans les Serial.print().

Description de la méthode

Tout d’abord nous devons ouvrir le fichier de destination avant d’effectuer des opérations dessus puis ne pas oublier de le fermer lorsqu’on a finit de l’utiliser.

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

Ensuite, il nous faut parcourir le fichier d’origine ligne par ligne.

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

Une fois qu’il est possible de parcourir le fichier, nous détectons la présence de « Serial.print » et « Serial.println » sur chaque ligne. Pour cela, nous créons une fonction qui va retourner la liste des positions de ces chaines de caractères sur chaque ligne.

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

Pour chaque ligne, si les chaines de caractères « Serial.print » et « Serial.println » ne sont pas détectées, nous écrivons la ligne dans le nouveau fichier telle quelle.

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

Dans le cas contraire, nous allons d’abord modifier les chaines « Serial.println » puis les chaines « Serial.print ». Pour chaque cas, nous vérifions que la fonciton F n’est pas déjà présente. Auquel cas, nous ne modifions pas la ligne et la recopions dans le fichier de destination.

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

Dans le cas contraire, nous détectons la position des parenthèses et des guillements puis nous récupérons la chaine de caractères

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

Enfin, nous remplaçons la chaine de caractère récupérée par la même chaine insérée dans la fonction F.

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

Avant d’écrire la ligne modifiée dans le fichier de destination.

fileb.write(line)

Voici un bon exemple de l’application d’un script Python pour se simplifier la vie. N’hésitez pas à nous dire en commentaire si ce tutoriel vous a été utile ou si vous trouvez des choses manquantes erronées ou à améliorer.

Code complet

Voici le code complet que vous pouvez recopier pour tester. Il vous suffit de modifier les adresses du fichier d’origine (filename) et du fichier de destination (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()

Améliorations possibles

  • Détection automatique des fichiers INO dans l’arborescence d’un répertoire.

Sources