Arduino PVG32 Radiocommande

Bonsoir william270peel

Il n'y a qu'à demander :wink:

Introduction de la simulation du joystick.

Les commandes ne sont pas sensibles à la casse.
La commande est JS pour Joystick Simulation.
Le format est JSjvvvvttt
j = numéro du joystick (de 0 à ..) 1 chiffre. Si absent, arrêt de toutes les simulations.
vvvv = valeur simulée, 4 chiffres. Si == 0 ou absent, arrêt de la simulation de ce joystick.
ttt = durée de la simulation, format libre. Si == 0 ou absent, pas de limite de temp de la simulation.

Exemples :
JS105122000 joystick 1 à 512 pour 2000 millisecondes.
JS10512 ttt == 0 ou absent, pas de limite de temps.
JS1 vvvvv == 0 ou absente, joystick 1 arrêt de la simulation.
JS sans paramètres, arrêt de toutes les simulations.

Quand une simulation est active sur un joystick, sa valeur n’est plus prise en compte.
Quand la simulation est terminée, la valeur du joystick et reprise en compte.

Exemple d’utilisation :
JS1051211000 Joystick 1 à 512 pour 11 secondes.
pour arrêter cette commande avant les 11 secondes :
JS1 ou JS10

Il y a des indications quant au fonctionnement du programme dans le moniteur.

Le programme :

/*
	Name:       AF_Vanne_Danfoss_PVG32_PVEM.ino
	Created:	17.12.2024
				modif william 20/01/2025
	Author:     jpbbricole/william270peel
	Remarque:	https://forum.arduino.cc/t/controle-distributeur-hydraulique-danfoss-pvg32/1325278/211
				https://assets.danfoss.com/documents/187048/BC152886483664fr-001401.pdf
	04.01.2025  torJoyInactZone individuelles #265
	05.01.2025  Ajout de torToBeDisable #265
	06.01.2025  Ajout de JoyInMin et joyInMax + amélioration display #300
	18.01.2025  TOR à 0 quand au neutre #442
	20.01.2025  Nettoyage du programme
	21.01.2025	Ajout de commandes de paramétrage #
	26.01.2025	Paramètre inversion PWM #
	26.01.2025	Simulation du joystick par commande #29
*/

//------------------------------------- Définition de l'objet vanne
struct vanneParamDef     // Définition des paramètres des vannes
{
	const int joystickPin; // Potentiomètre joystick
	const int joyInMin; // Lecture valeur minimum
	const int joyInMax; // Lecture valeur maximum
	const int joyInactZone; // Zone d'inaction
	const int electrovannesPin; // Commande électrovanne (EV) PWM
	const boolean evPwmReverse; // Si inversion signal PWM
	const int evPwmMin; // Electrovanne PWM minimum
	const int evPwmMax; // Electrovanne PWM maximum
	const int evPwmMiddeLow; // Electrovanne PWM milieu bas
	const int evPwmMiddleHigh; // Electrovanne PWM milieu haut
	int evStatus; // Etat de l'électrovanne 1 bas, 2, milieu, 3 haut
	const int torPin; // Commande tout ou rien
	int joyPosition; // Position du joystick
	int pwmValue; // Valeur du PWM
};
vanneParamDef vanne[] =
{
//	Joy		joyMin	joyMax	Inact	EV		PWM reverse		PWMmin	PWMmax	PWMm bas	PWMm haut	EV etat		TOR pin		Joy position	PVM
	{A0,	0,		1023,	1,		6,		false,			190,	46,		120,		136,		0,			7,			0,				0},
	{A1,	0,		1023,	1,		5,		false,			46,		190,	120,		136,		0,          4,			0,				0},
	{A2,	200,	823,	20,		3,		false,			170,	64,		120,		136,		0,          2,			0,				0},
	{A3,	0,		1023,	1,		9,		false,			56,		190,	120,		136,		0,          8,			0,				0},
};
const int vannesNombre = sizeof(vanne) / sizeof(vanne[0]); // Nombre d'electrovannes

const int torPinEtatOn = HIGH; // Etat pour commmander ON
boolean torToBeDisable = false; // Si TOR doit être désactivé

enum evStatusIndex {evStatusIndexNull, evStatusIndexBas, evStatusIndexNeutre, evStatusIndexHaut};
const String evStatusLabel[] = {"-", "BAS", "NEUTRE", "HAUT"}; // Etats de l'EV

const unsigned long displayTempo = 500; // Tout les 1/2 seconde
unsigned long displayMills = millis(); // Tout les 1/2 seconde, chrono

//------------------------------------- Paramétrage manuel (manPar)
struct manParDef
{
	boolean joyOn; // Si le paramétrage simulation du joystick est actif
	int joyValue; // Valeur simulée du joystick
	unsigned long joyTimeTempo; // Durée de la simulation
	unsigned long joyTimeMillis; // Durée de la simulation, chrono
};
manParDef manPar[]=
{
//	Manuel		Valeur	Tempo	Millis
	{false,		512,	0,		0},
	{false,		512,	0,		0},
	{false,		512,	0,		0},
	{false,		512,	0,		0},
};

void setup()
{
	Serial.begin(115200);
	// Initialiser les pins des joysticks et des électrovannes
	for (int v = 0; v < vannesNombre; v ++)
	{
		pinMode(vanne[v].electrovannesPin, OUTPUT);
		pinMode(vanne[v].torPin, OUTPUT);
		if (torToBeDisable)
		{
			digitalWrite(vanne[v].torPin, !torPinEtatOn); // TOR OFF
		}
		else
		{
			digitalWrite(vanne[v].torPin, torPinEtatOn); // TOR ON
		}
	}
	
	Serial.println("Systeme de commande d'electrovannes: " + String(vannesNombre));
	//cmdExecute("js0080020000");
	//cmdExecute("js1080015000");
	//cmdExecute("js2080010000");
	//cmdExecute("js308008000");
}

void loop()
{
	// Lire les valeurs des joysticks
	for (int v = 0; v < vannesNombre; v ++)
	{
		if (!manPar[v].joyOn) // Si pas valeur joystick manuelle
		{
			vanne[v].joyPosition = analogRead(vanne[v].joystickPin);  // Lecture joystick
		} 
		else // Valeur manuelle
		{
			vanne[v].joyPosition = manPar[v].joyValue;
		}
		// Conversion de la position du joystick (0-1023) à une valeur de PWM (evPwmMin-evPwmMax)
		vanne[v].pwmValue = map(vanne[v].joyPosition, vanne[v].joyInMin, vanne[v].joyInMax, vanne[v].evPwmMin, vanne[v].evPwmMax);
	}

	// Appliquer les commandes proportionnelles et TOR pour chaque électrovanne
	for (int v = 0; v < vannesNombre; v ++)
	{
		controlElectrovanne(v);
	}

	// Commandes
	if (Serial.available()) // Si commande
	{
		cmdExecute(Serial.readStringUntil('\n')); // Lire le port série juaqu'à nouvelle ligne
	}

	// Affichage des valeurs
	if (millis() - displayMills >= displayTempo) // Si c'est le moment d'afficher
	{
		for (int v = 0; v < vannesNombre; v ++)
		{
			Serial.print(String(v) + " " + evStatusLabel[vanne[v].evStatus] + " " + String(vanne[v].joyPosition) + " " + String(vanne[v].pwmValue) + "\t");
		}
		Serial.println("");
		displayMills = millis(); // Redémarrage du chrono
	}

	// Commande des joystick, timout
	for (int v = 0; v < vannesNombre; v ++)
	{
		if (manPar[v].joyTimeTempo != 0) // Si timer pour ce joystick en mode paramétrage manuel
		{
			if (millis() - manPar[v].joyTimeMillis >= manPar[v].joyTimeTempo) // Si fin du paramètre manuel
			{
				joySimulOff(v);
			}
		}
	}
}

void controlElectrovanne(int index)
{
	int pwmVanne = ( vanne[index].evPwmReverse == true) ? pwmVanne = 255 -vanne[index].pwmValue : vanne[index].pwmValue;
	 
	if (vanne[index].pwmValue > vanne[index].evPwmMiddleHigh + vanne[index].joyInactZone) // +x pour zône neutre
	{
		vanne[index].evStatus = evStatusIndexHaut; // Enregistrement de la position
		digitalWrite(vanne[index].torPin, torPinEtatOn);  // Activation TOR (12V)
		analogWrite(vanne[index].electrovannesPin, pwmVanne);  // Appliquer le PWM à l'électrovanne
	}
	else if (vanne[index].pwmValue < vanne[index].evPwmMiddeLow - vanne[index].joyInactZone) // -x pour zône neutre
	{
		vanne[index].evStatus = evStatusIndexBas; // Enregistrement de la position
		digitalWrite(vanne[index].torPin, torPinEtatOn); //Activation TOR (12v)
		analogWrite(vanne[index].electrovannesPin, pwmVanne);  // Appliquer le PWM à l'électrovanne
	}
	else
	{
		vanne[index].evStatus = evStatusIndexNeutre; // Enregistrement de la position
		digitalWrite(vanne[index].torPin, !torPinEtatOn); // TOR Off
	}

}

/*
	Les commandes ne sont pas sensibles à la casse.
	Commandes reconnues:
	JS pour joystick simulation
	JSjvvvvttt	j = numéro du joystice (de 0 à ...) vvv = valeur commande tttt = temps de la simulation en millisecondes
				j toujours 1 chiffre, vvvv toujours 4 chiffres et tttt libre, si ttt absent ou tttt = 0 simulation en continu
	JS20475200 Joystick 2 à 475 pour 200 millisecondes
	
	Si JS est sans paramètres, le programme remet tout les joystick en mode normal.
	Si vvvv = 0 ou absent passage du joystick j en mode normal
*/

void cmdExecute(String cmdRx) // Execution de la commande re?ue
{
	cmdRx.trim(); // Nettoyage de la commande
	cmdRx.replace(" ",""); // Supprimer les espaces
	cmdRx.toUpperCase(); // Tout en majuscules
	Serial.println("Commande recue:" + cmdRx);
	
	if (cmdRx.startsWith("JS")) // Si joystick simulation
	{
		cmdRx.replace("JS", ""); // Ne garder que les paramètres
		if (cmdRx == "") // Si pas de paramètres alors toutes simulation off
		{
				for (int v = 0; v < vannesNombre; v ++)
				{
					joySimulOff(v);
				}
		} 
		else
		{
			int joyNum = cmdRx.substring(0, 1).toInt(); // Numéro de vanne
			manPar[joyNum].joyValue = cmdRx.substring(1, 5).toInt(); // Valeur joystick
			manPar[joyNum].joyValue = constrain(manPar[joyNum].joyValue, 0, 1023);

			manPar[joyNum].joyTimeTempo = cmdRx.substring(5).toInt(); // Temps de la commande
			manPar[joyNum].joyTimeMillis = millis();// Chrono de la commande
			
			if (manPar[joyNum].joyValue != 0)
			{
				manPar[joyNum].joyOn = true;
			} 
			else
			{
				joySimulOff(joyNum);
			}
//Serial.println(joyNum);
//Serial.println(manPar[joyNum].joyValue);
//Serial.println(manPar[joyNum].joyTimeTempo);
		}
	}
	else
	{
		Serial.println("Commande inconnue !!!:" + cmdRx);
	}
}

void joySimulOff(int joyIndex)
{
	Serial.println("\tJoystick simulation OFF " + String(joyIndex));
	manPar[joyIndex].joyOn = false; // Arrêter le mode simulation du joystick
	manPar[joyIndex].joyTimeTempo = 0; // Arrêter la temporisation
}

Amuses toi bien :wink:

Bonne soirée
jpbbricole