Go Down

Topic: SPI avec TFT et MIRF (Read 2611 times) previous topic - next topic

BossOfScandalz

Bonjour à tous,

Je souhaite afficher des données reçu via nrf24l01 sur une écran "robot lcd", les 2 composants fonctionnes très bien indépendamment mais dès que qu'ils sont connectés ensemble, le programme bloque dans la lib mirf (je pense).
Etant donnée qu'ils fonctionnes tout les 2 en SPI, j'ai séparé le ce, csn du nrf avec le cs, ce et rst du TFT.

Voici le programme

Code: [Select]
#include <TFT.h>  // Arduino LCD library
#include <SPI.h>
#include <Mirf.h>     // Pour la gestion de la communication
#include <nRF24L01.h> // Pour les définitions des registres du nRF24L01
#include <MirfHardwareSpiDriver.h> // Pour la communication SPI

// pin definition for the Uno
#define cs   7
#define dc   6
#define rst  5
#define BLACK    0x0000 // noir
#define BLUE     0x001F // Bleu
#define RED      0xF800 // Rouge
#define GREEN    0x07E0 // Vert
#define CYAN     0x07FF // Cyan
#define MAGENTA  0xF81F // Magenta
#define YELLOW   0xFFE0 // Jaune
#define WHITE    0xFFFF // Blanc


TFT LCD = TFT(cs, dc, rst);


unsigned long temps1;
unsigned long temps2;
boolean F5 = true;

void setup() {


  LCD.begin();
  Serial.begin(9600);
  Mirf.cePin = 9; // Broche CE sur D9
  Mirf.csnPin = 10; // Broche CSN sur D10
  Mirf.spi = &MirfHardwareSpi; // On veut utiliser le port SPI hardware
  Mirf.init(); // Initialise la bibliothèque

  Mirf.channel = 1; // Choix du canal de communication (128 canaux disponibles, de 0 à 127)
  Mirf.payload = sizeof(long); // Taille d'un message (maximum 32 octets)
  Mirf.config(); // Sauvegarde la configuration dans le module radio

  Mirf.setTADDR((byte *) "nrf01"); // Adresse de transmission
  Mirf.setRADDR((byte *) "nrf02"); // Adresse de réception


  LCD.setRotation(1);
  LCD.background(WHITE);



}


/*//////////////////////////////////////////////////////////////////////////
  |             |
 y|             |
  |             |
  |      x      |
  /////////////////////////////////////////////////////////////////////////*/
void loop() {
   
  temps1 = millis();    // pour voir le temps du programme
  nrf24 ();   //programme de test skyduino
  kmParH (20, 20);
  temps2 = millis();
  temps1 = temps2 - temps1;
  Serial.print("Temps = ");
  Serial.println(temps1);

}

// Fonction pour afficher la valeur recu
void kmParH (byte x, byte y) {
  if (F5 == true) {
    LCD.drawRect(x, y, 73, 32, BLACK);  // x28, y61
    LCD.stroke(BLACK);
    LCD.setTextSize(1);
    LCD.text("km/h", x + 48, y + 2); //x76, y63  +48 +2
    LCD.setTextSize(2);
    LCD.text(".", x + 46, y + 16); //x74, y63+14 = 77    +46  +16
    F5 = false;
  }

  LCD.stroke(BLACK);
  LCD.setTextSize(4);
  LCD.text("28", x + 2, y + 2); // simulation de la reception pour verif affichage
  LCD.setTextSize(2);
  LCD.text("5", x + 57, y + 16);
}


void nrf24() {
  unsigned long time_message = millis(); // On garde le temps actuel retourné par millis()
   
  Serial.print("Ping ... ");
  Mirf.send((byte *) &time_message); // On envoie le temps actuel en utilisant une astuce pour transformer le long en octets
  while(Mirf.isSending()); // On attend la fin de l'envoi
   
  // Attente de la réponse
  while(!Mirf.dataReady()) { // On attend de recevoir quelque chose
    if (millis() - time_message > 1000 ) { // Si on attend depuis plus d'une seconde
      Serial.println("Pas de pong"); // C'est le drame ...
      return;
    }
  }
 
  // La réponse est disponible
  Mirf.getData((byte *) &time_message); // On récupère la réponse
 
  // On affiche le temps de latence (sans division par deux)
  Serial.print("Pong: ");
  Serial.print(millis() - time_message);
  Serial.println("ms");
 
  // Pas besoin de tester plus d'une fois par seconde
  delay(1000);
}


J'ai simplement fait un copier coller du programme de skyduino (a qui je remercie au passage).
J'ai (essayé de) regarder dans les librairies comment était géré les Chips select (CS ou CSN) et je me pose la question, est-il nécessaire d'activer ou désactiver dans le programme principal ?


sylvainmahe

#1
Jan 16, 2017, 10:48 am Last Edit: Jan 16, 2017, 10:48 am by sylvainmahe
Les registres DDRB (0x24) et SPCR (0x4c) de l'ATmega (328P j'imagine ?) doivent être configurés au minimum comme ça:
Code: [Select]
DDRB |= 0b00101100;
SPCR = 0b01010000;


La seule variante entre le branchement du TFT et du nRF24L01 doit être la pin SS ou CS ou CSN (slave select ou chip select), pour le coup pas commune et bien indépendante, et également le retour d'information de la part du nRF24L01 c'est à dire le MISO.

Ensuite pour la pin CE du composant nRF24L01, pour ma part je la laisse à l'état haut en permanence (c'est l'activation du TX ou RX), dans mon cas le composant est en permanence en RX, et dès qu'on souhaite envoyer une info il passe en TX juste le temps d'envoyer.

BossOfScandalz

Merci pour ta réponse,

oui j'utilise arduino nano 328p.
Pour le reglage des registres, je place ses 2 lignes dans le setup ?

Je ferais le test ce soir.


sylvainmahe

#3
Jan 16, 2017, 05:58 pm Last Edit: Jan 16, 2017, 06:00 pm by sylvainmahe
En fait faut vérifier que les classes Mirf spi etc... que tu utilises mettent bien ses bits la sur les 2 registres que j'ai indiqué.

Comprendre également: c'est possible qu'une classe "défait" ce que l'autre fait, autrement dit l'une met les bons bits, le MISO fonctionne, et l'autre enlève ça... Le MISO ne fonctionne plus.


DDRB et SPCR sont 2 defines AVR qu'utilise Arduino (inclues par la bibliothèque Arduino). Ça permet de modifier l'état des registres du microcontrôleur. SPCR permet de configurer le SPI.

Si tu rajoutes cela dans le setup (après tes includes) je pense que ce sera bien configuré, mais attend l'avis de quelqu'un qui connais les classes mirf TFT etc... que tu utilises, il y a sans doute une autre manière de résoudre ton problème.

BossOfScandalz

#4
Jan 16, 2017, 09:52 pm Last Edit: Jan 16, 2017, 10:03 pm by BossOfScandalz
Merci pour tes explications très claire

J'ai testé plusieurs choses:
-Si je met un programme qui gère uniquement le TFT mais pas le NRF => le programme tourne meme avec la présence du NRF connecté.
-Si je met un programme qui gère uniquement le NRF => le programme fonctionne uniquement si je déconnecte le TFT.

J'en déduis donc que le problème provient du TFT

Au voltmètre et avec le programme qui gère NRF + TFT, le CS du TFT à HIGH, par contre le csn du nrf est a 1.5V donc LOW

J'ai testé de rajouter les 2 lignes pour config les registres, le programme se comporte autrement (parfois le programme boucle, mais j'ai pas l'impression qu'ils a reçu réellement une donnée).


sylvainmahe

Ok très bien comme test.

Par contre si le programme boucle et que il y a appel de fonction vers ton nRF dans cette boucle c'est peut être normal de pas voir les pins forcément à l'état HAUT ou BAS comme il se devrait non? (à moins que le test est réalisé "à vide") Car les pins CS (SS) respectives commutent (très rapidement) dès qu'il y a à communiquer avec le composant en question (ce qui fausserait un voltmètre).


Quote
-Si je met un programme qui gère uniquement le TFT mais pas le NRF => le programme tourne meme avec la présence du NRF connecté.
Ton montage est t'il bien alimenté: combien de mA ?
Car sans le programme pour le nRF, on est bien d'accord que ce dernier est en veille (il ne consomme pratiquement rien).

Quote
-Si je met un programme qui gère uniquement le NRF => le programme fonctionne uniquement si je déconnecte le TFT.
Ce qui pourrait être une sous-alimentation.

Après, l'argument contraire est le fait que le nRF consomme vraiment que dalle, pas plus de 15mA/h il me semble, par contre l'écran consomme combien c'est ça aussi qu'il faut voir.


Encore une fois je pense qu'il faut attendre un expert des classes mirf et tft, car j'ai pas trop le temps de m'y plonger.

BossOfScandalz

Effectivement, je n'ai pas tout expliqué.
Le projet c'est un bateau RC, une radiocommande avec un arduino nano, l'ecran tft, un module nrf24l01 + pa + lna, les joysticks + potard et Interr.
Un recepteur pour le bateau avec arduino nano, un nrf24l01 + pa + lna, un gps

Les modules je les alimentes avec un regulateur lm317t regulé en 3.3V sous 5V (une resistance sépare chaque entrée du NRF de l'arduino comme sur le site carnet du maker)
Lorsque j'alimente l'arduino en USB sur le PC j'ai pas 5V à l'entrée du régulateur, du fait je me retrouve avec 3V (mais le nrf fonctionne quand même)
Les modules consomme 100mA.

L'écran TFT est alimenté sous 5V donc les entrée du tft sont reliées directement à l'arduino.

Je vais donc prendre le temps de modifier tout ça, j'ai récupéré des L1117 3.3 (min 4.7V en entrée pour avoir 3.3V en sortie, supporte 1A). Je vais également intercaller des convertisseurs de niveau (5V <=> 3.3V) pour le nrf. Afin de limiter un maximum un problème hardware.

J'avoue avoir voulu aller trop vite ...
Merci d'avoir pris le temps de me répondre.

Je fais les modifs et post les resultats

sylvainmahe

Quote
Lorsque j'alimente l'arduino en USB sur le PC j'ai pas 5V à l'entrée du régulateur
Curieux en effet, généralement les ports usb des pc sont donnés pour 5V 500mA

Également, faut savoir que le nRF24L01 a un régulateur de tension intégré qui accepte de 1.9V à 3.6V (datasheet: " 1.9 to 3.6V supply range").
Après, je sais pas si ce qu'il y a autour du composant (PA + LNA) veut du 3.3V nickel, je pense que oui.


Quote
Je vais également intercaller des convertisseurs de niveau (5V <=> 3.3V)
A priori c'est inutile, le nRF24L01 tolère 5V (datasheet: "5V tolerant inputs").



Pour te donner une idée pour débuger ton problème, dans mes montages je les alimente en 3.3V 100mA (LM78L33), j'utilise également des modules tout fait avec PA + LNA (https://www.tindie.com/products/ICStation/wireless-transmission-module4677/) que je configure en puissance max via un registre du nRF (0x06 ou RF_SETUP = 0bxxxxx11x), je communique avec le composant à la vitesse de 4Mhz (0x4c ou SPCR = 0bxxxxxx00) c'est à dire la vitesse SPI la plus rapide garantie par Atmel pour l'ATmega328P (datasheet: "the SPI is only guaranteed to work at fosc/4 or lower") quand le microcontrôleur tourne à 16Mhz, et les entrées/sorties pour communiquer fonctionnent en 5V sans résistance (directement ATmega sur nRF).


Sinon, as-tu regardé des tutos ou possibles bug avec les 2 classes mirf et tft en même temps? Peut être d'autres personnes rencontrent le même problème?

sylvainmahe

#8
Jan 18, 2017, 03:44 pm Last Edit: Jan 18, 2017, 03:45 pm by sylvainmahe
Juste une petite remarque à 2 balles comme ça:

Quand on voit ça:
Code: [Select]
#include <SPI.h>
#include <Mirf.h>     // Pour la gestion de la communication
#include <nRF24L01.h> // Pour les définitions des registres du nRF24L01
#include <MirfHardwareSpiDriver.h> // Pour la communication SPI


Et tout le merdier qui s'en suit, mais bon dieu comment Arduino et ce qui gravite autour peut t'il être qualifié comme un système pour débutants? Suis-je le seul à trouver tout ça complètement hallucinant?

Ce qui par ailleurs explique tout ce qu'on voit comme questions sur ce forum. La base est tellement merdique que tout ce qui en découle l'est aussi multiplié par 10 au moins...

Je ne comprend pas pourquoi la team Arduino ne réagit pas, tout ça est tellement une blague énorme.

BossOfScandalz

Quote
Sinon, as-tu regardé des tutos ou possibles bug avec les 2 classes mirf et tft en même temps? Peut être d'autres personnes rencontrent le même problème?
Oui j'ai regardé, un peu comme moi, les composants fonctionne indépendamment mais pas ensemble, mais j'ai pas forcément trouvé solution.

Quote
Et tout le merdier qui s'en suit, mais bon dieu comment Arduino et ce qui gravite autour peut t'il être qualifié comme un système pour débutants? Suis-je le seul à trouver tout ça complètement hallucinant?
J'imagine que c'est le fait d'appeler plein de librairie pour la même chose ?
J'ai suivi le tuto du carnet du maker, car il est bien expliqué, il explique également les fonctions de la librairie, j'ai pas cherché a comprendre.

J'ai vu qu'il existe une autre librairie RF24.
Quesque tu me conseillerais d'utiliser ?

Avant d'utiliser des NRF24L01 j'utilisais des NRF905, j'ai du enlever la librairie pour que mon programme sort dans le cas ou aucune réception était pendant 1 seconde.

Quesque tu me conseil comme librairie simple pour un débutant comme moi (j'ai pourtant certaine notion en électronique mais moins en prog)

Merci

sylvainmahe

Quote
..., j'ai du enlever la librairie pour que mon programme sort dans le cas ou aucune réception était pendant 1 seconde.
:( C'est vraiment con comme truc.

Quote
J'imagine que c'est le fait d'appeler plein de librairie pour la même chose ?
Pour la même chose et pour que sa marche surtout, leur bibliothèques sont prévues comme ça, pour qu'on s'emmerde un max, et qu'on soit un max dépendant de leur philosophie de programmation.

Quote
J'ai suivi le tuto du carnet du maker, car il est bien expliqué, il explique également les fonctions de la librairie, j'ai pas cherché a comprendre.
Tu as bien fait, de toute façon ce n'est pas ta faute et encore heureux, tu n'as fait que ce que font des millions de gens sur la planète qui veulent faire de l'électronique et apprendre à la programmer, c'est à dire s'enquiller dans le système Arduino pour le meilleur et pour le pire.


Quote
Quesque tu me conseil comme librairie simple pour un débutant comme moi (j'ai pourtant certaine notion en électronique mais moins en prog)
Je ne doute pas que tu es bon en électronique.

Je ne peux sur ce forum Arduino pas être de bon conseil puisque j'ai développé mon propre système (je n'utilise pas Arduino), mes propres classes qui gèrent des composants tel le nRF24L01P, et mes propres cartes électroniques. Donc je ne peux te conseiller que ce que tu utilises déjà.

Je ne peux en fait que constater tous les jours ce que j'appelle maintenant "le merdier Arduino et les gens qui malheureusement le subissent", tout en étant certain que chez certaines personnes cela pourra se traduire par un dégoût pur et simple de l'électronique (par faute d'avoir débuté avec quelque chose de vraiment valable).

C'est comme ça on y peut rien :(

BossOfScandalz

J'ai modifié le regulateur, je dispose maintenant d'un 3.3V niquel, condo de 10µ en sortie du regul, ceci pour la RC et le recepteur.
J'ai également déplacé le CSN du NRF sur la broche 4 (j'ai lu qu'il etait possible d'avoir des parasites ...). Lorsque j'aurais trouvé le défaut, je ferais un test de remettre sur la 10.

Après test toujours un problème, j'ai finalement déconnecté la broche MISO du TFT qui après réflexions ne me sert pas.

Maintenant j'arrive a communiqué avec un programme qui dispose que la partie MIRF, avec en prime le TFT toujours connecté sur l'arduino nano.
En revanche, toujours pas de communication avec un programme TFT + MIRF sur la RC. mais l'écran affiche mes données, et sur le serial moniteur, j'ai mon programme qui boucle (donc le RC est sensé envoyer une donnée et attendre de recevoir) seulement le recepteur (bateau) lui ne recoit rien, donc emet aucun signal normalement.

Je ne comprend donc pas qu'elles données la RC reçoit ??

Je vais pouvoir maintenant revoir le programme pour faire le plus simple possible.

Quote
Je ne peux sur ce forum Arduino pas être de bon conseil puisque j'ai développé mon propre système (je n'utilise pas Arduino), mes propres classes qui gèrent des composants tel le nRF24L01P, et mes propres cartes électroniques. Donc je ne peux te conseiller que ce que tu utilises déjà.
Je viens de visiter ton site internet et je dis "respect" pour ton projet MODULE℠.
J'imagine que tu debug facilement tes programmes avec tes classes perso dont est elles sont toutes retro-compatible.

A quand la classe TFT  ;D







BossOfScandalz

Après un programme simpliste, le problème survient si je place
Code: [Select]
LCD.begin();
 après
Code: [Select]
 Mirf.init();

ou si j'effectue un affiche, le TFT prend la main et le NRF ne communique plus.

Je ne peux pas modifier la lib TFT, je vais donc tester d'autre librairie.

Si vous avez des suggestions a me faire part

sylvainmahe

Quote
J'ai modifié le regulateur, je dispose maintenant d'un 3.3V niquel, condo de 10µ en sortie du regul, ceci pour la RC et le recepteur.
Ok génial ;) C'est déjà ça de réglé.

Quote
Après test toujours un problème, j'ai finalement déconnecté la broche MISO du TFT qui après réflexions ne me sert pas.
Ok d'accord, de toute façon ce MISO c'est le retour d'infos de la part du composant qui pilote l'écran tft, et j'imagine que tu veux envoyer des infos vers l'écran, mais que tu n'as aucune utilité d'en recevoir.

Par contre étant donné que l'écran et le nrf ont 2 "cable select" (CS) bien distincts, ce MISO ne devrait pas poser de problème. Chez moi j'ai testé avec 3 nRF24L01P sur un même ATmega328P, donc les 3 MOSI MISO SCLK sont communs, sauf les CS, et ça fonctionne sans problème.

Quote
seulement le recepteur (bateau) lui ne recoit rien, donc emet aucun signal normalement.
Es-tu sûr d'avoir indiqué une même clé unique pour la communication entre les 2 nrf?



Quote
J'imagine que tu debug facilement tes programmes avec tes classes perso dont est elles sont toutes retro-compatible.
Merci pour ton commentaire, mais mon but ici est un peu brisé du coup car mon projet est un sujet polémique dont je ne peux faire usage pour aider les gens. Par contre je peux aider les gens avec l'expérience que j'ai eu grâce à ce projet effectivement, c'est ce que j'essaye de faire mais c'est pas évident car les bibliothèques concurrentes sont très bordéliques !

C'est évident que c'est extrêmement facile pour moi maintenant de créer n'importe quel programme, et c'est un vrai plaisir de programmer un main.cpp dans ces conditions la. J'ai avant toute chose créé ce projet Module pour me faciliter la programmation de nouveaux projets, mais maintenant que c'est bien rodé si ça peut servir à d'autres, pourquoi pas, c'est un des buts.

Quote
A quand la classe TFT  ;D
Tu sais que j'aimerais bien (rien que pour combler les demandes que j'ai eu en ce sens), personnellement j'ai pas encore eu l'application de ce genre d'écran parce que j'utilise mes afficheurs à led qui dans mon esprit ont un coté plus vintage que j'aime bien, et sont dédiés à l'affichage de caractères à la fois numérique mais aussi alpha (numérique).

Par contre cela ne m'a pas empêché d'en acheté un une fois mais la conception même de l'écran m'a déplu donc je l'ai donné à quelqu'un. J'étais parti pourtant pour en faire une classe, j'avais commencé à réfléchir à des fonctions de tracé de polygones et d'anticrénelage.

J'ai moi aussi en projet (futur) une radiocommande avec mes afficheurs à led, mais je réfléchi encore si je dois fabriquer les joystick en alu avec le système 2 axes ou si j'en achète des tous faits... La c'est plus la contrainte de passer des journées devant ma fraiseuse avec le coût en électricité que ça implique (triphasé).


Quote
ou si j'effectue un affiche, le TFT prend la main et le NRF ne communique plus.

Je ne peux pas modifier la lib TFT, je vais donc tester d'autre librairie.

Si vous avez des suggestions a me faire part
Ok, et si tu place Mirf.init(); après ça donne quoi?

Si j'ai le temps je vais essayer de regarder dans les classes que tu utilises voir ce que sa donne.

sylvainmahe

J'imagine que tu as vu ce topic (vu tes précédentes réponses).

Tu sembles avoir fait plus ou moins ce qu'ils ont indiqués mais ça ne fonctionne toujours pas.
Tu as raison peut être il va falloir aller voir d'autres bibliothèques (classes) car ça semble mal barré.

Je viens de regarder un petit peu les fichiers dépendants de Mirf.h et TFT.h, c'est à dire (entre autres):
Code: [Select]
Adafruit_GFX.h
Adafruit_ST7735.h
limits.h
nRF24L01.h
MirfHardwareSpiDriver.h
MirfSpiDriver.h
MirfSpiDriver.cpp
stdio.h
pins_arduino.h
wiring_private.h
SPI.h
Print.h
gfxfont.h
WProgram.h
avr/pgmspace.h
pgmspace.h
avr/io.h
glcdfont.c


Mise à part la vision d'un tel "merdier" mal codé, j'ai vu des différences que j'ai noté:

Code: [Select]
Mirf.cpp:
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_2XCLOCK_MASK);

Adafruit_ST7735.cpp:
SPI.setClockDivider(21); //4MHz
SPI.setDataMode(SPI_MODE0);

MirfHardwareSpiDriver.h:
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_2XCLOCK_MASK);

Soit SPI_2XCLOCK_MASK et 21 à remplacer partout SPI_CLOCK_DIV4, mais honnêtement je pense que ça ne résout rien (même si ça nous fait revenir un peu dans le domaine d'application donné par le constructeur).

On voit que TFT.h "d'Arduino" c'est en fait l'utilisation de Adafruit_ST7735.cpp et .h.

Enfin voila je sais pas trop, après j'ai peut être loupé quelque chose, mais c'est difficile à dire ou.

Go Up