come proteggere il codice da lettura

Premessa:
parliamo di FIRMWARE. Il sorgente se non lo distribuisci, non è clonabile. Il FIRMWARE può essere estratto da un microcontrollore e riflashato pari pari. Puoi anche disassemblarlo per recuperare il programma sotto forma di linguaggio macchina (assembly), ma non puoi riottenere in alcun modo il sorgente in linguaggio C/Arduino.

Detto questo, esistono alcuni registri interni chiamati fuse ed altri chiamati lock bit.
I lock bit possono bloccare l'accesso alla memoria, ma in lettura.
Ti consiglio la lettura di questo doc:
http://www.avrfreaks.net/index.php?func=viewItem&item_id=301&module=Freaks%20Tools
Con i lock bit il codice non può più essere estratto dal microcontrollore.

Poi puoi ulteriormente bloccare il chip anche in scrittura, disattivando ad esempio la programmazione SPI ed il pin di reset.
Ti consiglio questo sito:
http://www.engbedded.com/fusecalc
Puoi così trovare i valori per i fuse da impostare.
Occhio che se disattibi il pin di reset, poi ti serve un programmatore detto "H/V" (alta tensione, anche se poi sono 12V) per poterlo sbloccare.