Salut,
C'est effectivement un problème classique que l'on rencontre quand on utilise des valeurs signées et non signées en même temps et sans en tenir compte...
Par contre techniquement parlant il n'y a pas de "dépassement" ou autre d'un char, je m'explique!
Pour commencer même si on parle de valeur signée ou non, en vrai en informatique la notion n'existe pas (c'est juste une abstraction rajoutée), les registres ou autres ont juste des valeurs binaires composées donc d'un ensemble de 1 ou 0 mais il n'y a pas de notion de négatif ou positif.
bref pour reprendre l'exemple,
la valeur de i est un unsigned int, donc une valeur codée sur 2 ou 4 octets (ça dépend de l'arduino utilisé), prenons 2 octets pour l'exemple.
Notre i va varier de 00000000 00000000b à 00000000 11111111b
cette variable est mise dans un char codé sur un octet ce qui nous fait qu'en fait on tronque l'int de son octet de poids fort pour garder que le deuxième (poids faible)
Ce tableau aura donc en
première "case" (00000000) 00000000b (partie tronquée entre parenthèses)
deuxième "case" (00000000) 00000001b
...
127eme case (00000000) 01111111b
128eme case (00000000) 10000000b
129eme case (00000000) 10000001b
...
255eme case (00000000) 11111110b
256eme case (00000000) 11111111b
On voit donc que aucun dépassement n'est arrivé (mis a par le passage int en char mais l'octet de poids fort est toujours à 0), en revanche puisque tu as déclaré un "char" qui est officiellement signé, ta fonction de print va essayer de réaliser l'abstraction du signe qui est basiquement le premier bit d'une valeur signée est le signe, si c'est un 0 c'est positif si c'est un 1 c'est négatif.
C'est pourquoi l'affiche jusque la 127eme case reste "normale", le char commence par 0, donc on l'affiche comme du positif
A partir de la 128eme case, le premier bit passant à 1, il est considéré négatif, et donc la fonction print va envoyer la représentation du contenu de cette case en négatif
Toussa pour dire que ce comportement n'est pas du tout inattendu et n'est juste que la représentation finale qui est réalisée en utilisant un mauvaise "encodage" (comme si tu veux afficher un texte encodé en Unicode en le décodant avec du ISO 8859, le texte ne sera pas lisible directement, même si le contenu de ton fichier n'est en fait pas changé)
Pour le code en lui même, il est plutôt conseiller d'utiliser le type byte pour des valeurs non signées sur un octet (à la place de unsigned char) même si le résultat sera le même. De même stocker une valeur codée sur plus d'octets que celle de stockage (ici mettre un int dans un byte) amène très souvent à des gros problèmes (pas le cas ici) puisque qu'en tronquant les valeurs, tu vas réduire la plage de valeur possibles et avoir des "bouclages".
Cordialement