Je conçois un pousse seringue électrique

Bonjour! Je conçois un dispositif médical (pousse seringue électrique), c’est un système qui utilise un moteur à CC (généralement pas à pas) il possède un clavier 4*3 et un afficheur LCD 16*2 ## mise en situation
Bon j’ai un problème au niveau de mon programme, je veux faire un code qui demande à l’utilisateur d’entrer des valeurs (volume et temps) puis calcule la vitesse qui sera celle du moteur et affiche à l’écran. Mais j’ai un problème, le clavier déjà ne donne pas la bonne valeur ( mais renvoie son état genre 5 pressé et 5 relâché) et n’effectue pas le calcule
Si vous pouvez m’aider :pray:t4:

:warning:

Post mis dans la mauvaise section, on parle anglais dans les forums généraux. ➜ déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans « Les bonnes pratiques du Forum Francophone”

——

Pour votre question il semble que vous ayez un peu de boulot devant vous à faire des tutos.

Mon tuto sur comment bien écouter le port série ou gérer un flux asynchrone genre keypad pourrait être utile ➜ petit tuto sur le sujet

sinon pour bien débuter avec l’arduino, un bon point de départ c’est de lire les tutos d’eskimon

Merci bien :pray:t4:

Ce serait bien de nous mettre le code que tu utilises aussi

Bonjour ulrichnwar

Il y a quelque temps, j'ai fait ça:

ça pourrait être aisément extrapolé en pousseur de seringue.

La liaison avec le smartphone se fait en Bluetooth, le clavier est un clavier standard mais interfacé en i2C par un circuit PCF8574.

Si tu est intéressé...

Cordialement
jpbbricole

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
const int stepsPerRevolution = 200;  
 
 
// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 2, 3, 4, 5);
 
LiquidCrystal_I2C lcd(0x27,16,2);
#include "Adafruit_Keypad.h"
#define KEYPAD_PID3845
#define R1    13
#define R2    12
#define R3    11
#define R4    10
#define C1    9
#define C2    8
#define C3    7
const byte ROWS = 4; // rows
const byte COLS = 3; // columns
// define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
   {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}, {'*', '0', '#'}};
byte rowPins[ROWS] = {R1, R2, R3,
                     R4};         // connect to the row pinouts of the keypad
byte colPins[COLS] = {C1, C2, C3}; // connect to the column pinouts of the
                                  // keypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
 
void setup()
{
 customKeypad.begin();
 lcd.init();
 lcd.backlight();
 //lcd.setCursor(0,0);
 //lcd.print("BIENVENU EN MAB3!");
 //delay(2000);
 //lcd.setCursor(1,1);
 //lcd.print("  PROJET PSE");
 //delay(3000);
 //lcd.setCursor(0,0);
 //lcd.clear();
 //delay(1000);
 //lcd.print("    PATIENTEZ     ");
 //delay(1000);
 //lcd.clear();
 lcd.setCursor(0,0);
 lcd.print("     UTILISEZ    ");
 lcd.setCursor(0,1);
 lcd.print("*:RETOUR    #:OK");
 delay(2000);
 lcd.clear();
 delay(100);
 
 
 
 }
 
 
void loop()
{//lcd.setCursor(0,0);
   //lcd.print("Entrer volume ");
 customKeypad.tick();
 while(customKeypad.available()){
   keypadEvent e = customKeypad.read();
   //lcd.setCursor(18,20);
   lcd.write(e.bit.KEY);
 
 }
 delay(1);
  myStepper.setSpeed(100);
 //lcd.print("clockwise");
 myStepper.step(stepsPerRevolution);
 delay(1);
}

Voici où j’en suis avec mon code mais j’ai quelques difficultés d’acquisition des chiffres entrés au clavier
Également je voudrai que le programme demande à l’utilisateur d’entrer le volume et le temps puis calculer la vitesse qui sera celle du moteur mais j’ai du mal, j’ai essayé plusieurs codes mais rien ne fonctionne comme je veux

Salut :wave:
Svp pouvez-vous m’aider avec le code que vous avez utilisé pour piloter le moteur avec le clavier ?:pray:t4::pray:t4:

Comment sont entres les données ? Vous utilisez # et * pour des commandes particulières?

vous pouvez jeter un oeil à mon petit tuto sur la gestion asynchrone d’acquisition de données, il y a un exemple à la fin d’utilisation du keypad pour saisir de l’info.

Sinon C’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

Oui oui exactement, * et # sont mes commandes particulières et le reste juste des entrées

mon petit tuto sur la gestion asynchrone contient un code qui permet d'attendre une entrée sur le clavier. Jetez y un oeil

Bonjour ulrichnwar

Je te mets le programme en entier, la différence avec ton montage, mon clavier est en i2C, mais la transposition doit être assez facile.

/*'************************************************************************************************
'*  Name    : ButeePositionnementMpapClavier.ino                                              
'*  Author  : jpbbricole                                                                         
'*                                                                                                
'*  Date    : 12.05.2022                                                                          
'*  Version : 0.1                                                                                 
'*  Notes   : Butee mobile positionnée par moteur pas à pas, clavier et écran LCD 20x4                                                  
'*	Commandes possibles: HOME    GOTOMM=2200                                                    
'**************************************************************************************************
*/
#include <Wire.h>                                          // Comes with Arduino IDE
#include <AccelStepper.h>     // http://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html 
                              // https://www.pjrc.com/teensy/td_libs_AccelStepper.html
#include <SoftwareSerial.h>
#include <Keypad_I2C.h>     // https://github.com/joeyoung/arduino_keypads
#include <Keypad.h>

//------------------------------------- Affichage LCD
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20, 4);                         // 0x27 = adresse sur bus i2C, peut ?tre 0x3f
String lcdEmptyLine = "                    ";


#define mpapXdirPin 5     //  pin DIR sur interface A4988
#define mpapXstepPin 6     //  pin STEP sur interface A4988
#define mpapXenaPin 7     //  pin ENABLE connecte sur interface A4988

const float mpapMaxSpeed = 600.0;
const float mpapAcceleration = 9000.0;
const float mpapPasTours = 200.0;
const float mpapDistanceMax = 280.0;     // Pour une vis, sa longueur
const float mpapDistanceTours = 4.0;     // Pour une vis, le pas
const float mpapHomeOffsetTo0mm = 2.2;     // Distance entre homing et 0mm
const boolean mpapDirReverse = true;     // Pour inverser la direction

struct mpapDef {String name; String scaleUnit; long scaleStepsMax; long scaleMm100Max; float scaleMm100Steps;
	            long posSteps; long posMm100; float homeOffsetTo0mm;};

//------------------------------------- Moteurs X (mpapX)
AccelStepper mpapX(1, mpapXstepPin, mpapXdirPin);     // Creation du mpapX 1

mpapDef mpapXpar =       // Creation des paramètres du mpapX 
{

//    name      scaleUnit
	"Règle H",   "mm",      // "POSX"
	
	(mpapDistanceMax/4) * mpapPasTours,     //Nombre de pas sur toute l'échelle (scaleStepsMax)
	mpapDistanceMax * 100,     // Nombre de 1/100 mm sur toute l'échelle (scaleMm100Max)
	(mpapDistanceTours/mpapPasTours)*100,     // Nombre de 100/mm par pas (scaleMm100Steps)
	0,     // Position en pas (posSteps)
	0,     // Position en 1/100 mm (posMm100)
	mpapHomeOffsetTo0mm     // Offset entre homing et 0 mm de la règle, en mm (homeOffsetTo0mm)
};

//------------------------------------- Clavier 4x4 i2C (keyb)
#define keybI2cAddress 0x38                                          // Adresse de l'interface clavier a base de PCF8574  (Sabeldom 0x20)
const byte keybRowsNbr = 4;                                          // 4 lignes
const byte keybColsNbr = 4;                                          // 4 colonnes

char keys[keybRowsNbr][keybColsNbr] = {
	{'1','2','3','A'},
	{'4','5','6','B'},
	{'7','8','9','C'},
	{'.','0','#','D'}
};
//--------------------------------- Connexions du clavier su l'interface i2C PCF8574 i/o port
byte keybRowPins[keybRowsNbr] = {7, 6, 5, 4};                        //connect to the row pinouts of the keypad
byte keybColPins[keybColsNbr] = {3, 2, 1, 0};                        //connect to the column pinouts of the keypad

Keypad_I2C keybI2c( makeKeymap(keys), keybRowPins, keybColPins, keybRowsNbr, keybColsNbr, keybI2cAddress, PCF8574 );

struct keybDef
{char inputChar; String inputStr; int maxLenght; bool newreceived; String command;};
keybDef keyboard;

//------------------------------------- Capteur Home
#define homeXsensorPin 8     // X Capteur a effet de Hall
const int homeXsensorOnStat = LOW;     // Etat du signal Home actif

//------------------------------------- Bluetooth (bt)
const int btTxPin = 4;
const int btRxPin = 3;

SoftwareSerial btSerial(btRxPin, btTxPin); // RX, TX
bool btCmdNew = false;      // Si une nouvelle commande a été reçue
String btCmd = "";               // Texte de la commande

//------------------------------------- App Inventor (appInv)
boolean appInvisPresent = false;     // Si MAI est présent
boolean appInvMessageEcho = true;
const String appInvDataSeparator = "=";
const String appInvMessageTerminaison = "\n";

//------------------------------------- Commandes depuis moniteur
bool cmdmonNew = false;                            // Si une nouvelle commande a été reçue
String cmdmonCmd = "";                                 // Texte de la commande reçue
enum cmdMonFctIndex {cmdFctGotoMm, cmdFctHome, cmdFctTest, cmdFctLasted};
char* cmdMonFctLabel[] = {"Goto mm", "Home", "Test"};
char* cmdMonFctCmd[] = {"GOTOMM", "HOME", "TEST"};

void setup()
{
	Serial.begin(115200);
	btSerial.begin(9600);

	Wire.begin();                                          // Démarrer le bus i2C nécessaire à l'affichage
	keybI2c.begin( );
		
	lcd.init();                                          // Démarrer l'affichage LCD
	lcd.noBacklight();
	delay(500);
	lcd.backlight();
	lcdPrint("* * butee MPAP * *", 0, 0);
	
	keybInitialisation();
	pinMode(homeXsensorPin, INPUT);
	mpapInitialisation();
	//mpapGotoHome();     // Homing automatique au démarrage
	affichStatusDisplay();
}

void loop()
{
	//--------------------------------- Lecture du clavier
	keyboard.inputChar = keybI2c.getKey();

	if (keyboard.inputChar != NO_KEY)
	{
		keybPressed(keyboard.inputChar);
		if (keyboard.newreceived)     // Si commande clavier terminée
		{
			if ((keyboard.command.indexOf("000") == 0) && (keyboard.command.length() == 3))
			{
				cmdMonExecute("HOME");
			} 
			else
			{
				cmdMonExecute("GOTOMM=" + keyboard.command);
			}
				
			keyboard.command = "";
			keyboard.newreceived = false;
		}
	}
	
	//--------------------------------- Commandes venant du moniteur
	serialLecture();
	if (cmdmonNew)     // Si une nouvelle commande depuis le moniteur GOTOMM100=2200
	{
		cmdMonExecute(cmdmonCmd);

		cmdmonCmd = "";
		cmdmonNew = false;
	}
  
  //--------------------------------- Ecoute du port Bluetooth
  btSerialLecture();
  if (btCmdNew)      // Si une nouvelle commande depuis le moniteur
  {
//Serial.println(btCmd);
	  cmdMonExecute(btCmd);
	  
	  btCmd = "";
	  btCmdNew = false;
	  appInvisPresent = true;
  }
}

//===================================== MPAP ==================================
//------------------------------------- Initialisation

void mpapInitialisation()
{
	mpapX.setMaxSpeed(mpapMaxSpeed);
	mpapX.setAcceleration(mpapAcceleration);
	mpapX.setEnablePin(mpapXenaPin);
	//                          DIR        STEP   ENA
	mpapX.setPinsInverted(mpapDirReverse, false, true);
	mpapX.enableOutputs();     // Activer les signaux du MPAP
	
	mpapPosReset();
}

float mpap100mmToSteps(int mm100)
{
	return mm100/mpapXpar.scaleMm100Steps;
}

float mpapStepsToMm100(long steps)
{
	return mpapXpar.scaleMm100Steps*(float)steps;
}

//===================================== App Inventor (appInv)
void appInvUpdate()
{
	//if (!appInvisPresent){return;}

	appInvMessageSend("POSMM", String(mpapXpar.posMm100 / 100.0));
	delay(500);
	appInvMessageSend("POSSTEPS", String(mpapXpar.posSteps));
	delay(500);
}

void appInvMessageSend(String aiCmd, String aiParam)
{
	String appInvMessage = aiCmd + appInvDataSeparator + aiParam;

	Serial.println("AppInv message >>> " + appInvMessage);

	btSerial.print(appInvMessage + appInvMessageTerminaison);
}

//================================== Affichage ===============================
void affichStatusDisplay()
{
	int stepPos = mpapXpar.posSteps;
	long pos100mm = mpapXpar.posMm100;
	float posMm = (float)pos100mm/100.0;
	
	lcdPrint("mm", 4, 1); lcdPrint("Pas", 13, 1);
	lcdPrintLength(String(posMm), 2, 2, 6);
	lcdPrintLength(String(stepPos), 12, 2, 6);
	

	String lineA = "mm: " + String(posMm);
	String lineB = "Pas : " + String(stepPos);

	appInvUpdate();
}

void affichInformations(String txtInfoA, String txtInfoB)
{
	if (txtInfoA == "")                                                         // Si texte vide, effacer la ligne information
	{
		lcdClsRow(3);
	}
	else
	{
		lcdPrint(txtInfoA  + txtInfoB, 0, 3);
	}
}

//================================== Périfériques ===============================
//------------------------------------- Homing
void mpapGotoHome()
{
    if (digitalRead(homeXsensorPin) == homeXsensorOnStat)     // Si déjà home
    {
	    affichInformations("Quitter  ", "FDC < < ");
	    mpapX.runToNewPosition(mpapX.currentPosition() + mpapPasTours * 3);
    }

    affichInformations("Recherche ", "FDC >>> ");
    mpapX.moveTo(-(mpapXpar.scaleStepsMax + 200));     // Reculer
    mpapX.setMaxSpeed(mpapMaxSpeed / 1);     // On accèlère
    while (digitalRead(homeXsensorPin) != homeXsensorOnStat)    // Tant que pas home
    {
	    mpapX.run();
    }
	mpapPosReset();

	mpapGotoMm100(mpapXpar.homeOffsetTo0mm * 100);     // Se positionner au début de la règle	
	mpapPosReset();
	affichInformations("", "");     // Effacer la ligne d'information
}

void mpapGotoMm100(long targetMm100)
{
	mpapCheckValues(targetMm100);
	
	mpapX.runToNewPosition(mpapXpar.posSteps);
}

void mpapCheckValues(long gotoMm100)     // Mise à de la position des MPAP en 1/100mm
{
	if (gotoMm100 > mpapXpar.scaleMm100Max) {gotoMm100 = mpapXpar.scaleMm100Max;}
	if (gotoMm100 < 0) {gotoMm100 = 0;}

	mpapXpar.posSteps = mpap100mmToSteps(gotoMm100);
	mpapXpar.posMm100 = mpapStepsToMm100(mpapXpar.posSteps);
}

void mpapPosReset()     // Mise a 0 du MPAP
{
	mpapX.setCurrentPosition(0);
	mpapCheckValues(0);
}

void mpapDisplayStatus()
{
	int stepPos = mpapXpar.posSteps;
	long pos100mm = mpapXpar.posMm100;
	float posMm = (float)pos100mm/100.0;
}

//================================== Commandes ===============================

void cmdMonExecute(String cmdStr)
{
	float fctValue;
	int fctFlagIndex;
	String fctName = "";
	String fctValueStr = "";
	
	cmdStr.toUpperCase();
	
	fctFlagIndex = cmdStr.indexOf("=");
	if (fctFlagIndex > 0)
	{
		fctValueStr = cmdStr.substring(cmdStr.indexOf("=")+1);          // Controle s'il y a = dans la commande
	}
	else
	{
		fctValueStr = "0";
	}

	fctValueStr.replace(",", ".");     // Remplacer une virgule éventuelle.
	fctValue = fctValueStr.toFloat();
	fctName = cmdStr.substring(0, cmdStr.indexOf("="));
	
	int fctIndex = cmdMonFunctionGetIndex(fctName);
	
	if (fctIndex  != -1)                                               // Si fonction reconnue
	{
		Serial.println("Execution de : " + cmdStr);
		affichInformations((String)cmdMonFctLabel[fctIndex] ,  "=" + fctValueStr);
		
		cmdFctExecute(fctIndex, fctValue);
	}
	else
	{
		Serial.println("Fonction erreur!");
		Serial.println(">>> " + cmdStr + " <<<");
	}
	affichInformations("", "");
	affichStatusDisplay();
}

int cmdMonFunctionGetIndex(String monCmd)              // Recherche l'index de la commande re?ue
{
	int retVal = -1;
	monCmd.toUpperCase();
	
	for(int i = 0; i < cmdFctLasted; i++)
	{
		String cmdSearch = cmdMonFctCmd[i];
		if (cmdSearch == monCmd)
		{
			retVal = i;
			break;
		}
	}
	return retVal;
}

void cmdFctExecute(int fctIndex, float fctParamFloat)
{
	switch (fctIndex)
	{
		case cmdFctGotoMm:
			mpapGotoMm100((long)(fctParamFloat * 100));
			break;
		case cmdFctHome:
			mpapGotoHome();
			affichStatusDisplay();
			break;
		case cmdFctTest:
			//long pos100mm = mpapXpar.posMm100;
			//float posMm = (float)pos100mm/100.0;

			appInvMessageSend("POSMM", String(mpapXpar.posMm100 / 100.0));
			break;
	}
}

//===================================== Clavier
// * = point    # = Enter    C = correction    A = escape
void keybPressed(char keyPress)
{
	if ((keyPress >= '0') && (keyPress <= '9'))     // Siu des chiffres
	{
		keybStrAddChar(keyPress);
	}
	else if (keyPress == 'C')     // Touche correction
	{
		keybStrDelChar();
	}
	else if (keyPress == 'A')     // Touche escape
	{
		keyboard.inputStr = "";
		keyboard.command = keyboard.inputStr;
		keyboard.newreceived = false;
	}
	else if (keyPress == 'B')     // Touche Break
	{

	}
	else if (keyPress == '.')
	{
		if ((keyboard.inputStr.length()) && (keyboard.inputStr.indexOf(".") == -1))     // Si pas déjà le point
		{
			keybStrAddChar(keyPress);
		}
	}
	else if ((keyPress == '#'))
	{
		keyboard.command = keyboard.inputStr;
		if (keyboard.command != "")
		{
			keyboard.newreceived = true;
		}
		keyboard.inputStr = "";
	}
	else
	{
		Serial.println("Touche non traitee " + keyPress);
	}
	keybInputDisplay();
}

void keybStrAddChar(char addedChar)
{
	if (keyboard.inputStr.length() < keyboard.maxLenght)
	{
		keyboard.inputStr += String(addedChar);
	}
	else
	{
		Serial.println("Beep");
	}
}

void keybStrDelChar()
{
	if (keyboard.inputStr.length() > 0)     // Si déjà des caractères
	{
		keyboard.inputStr = keyboard.inputStr.substring(0, keyboard.inputStr.length()-1);
	}
	else
	{
		Serial.println("Beep");
	}
}

void keybInputDisplay()
{
	if (keyboard.inputStr != "")
	{
		affichInformations("Clav" ,  "=" + keyboard.inputStr + " ");
	} 
	else
	{
		affichInformations("", "");     // Effacer la ligne d'information
	}
}

void keybInitialisation()
{
	keyboard.maxLenght = 10;
	keyboard.inputStr = "";

	keyboard.newreceived = false;
	keyboard.command = "";
}

//================================== Communications ===============================
//------------------------------------- Réception de commandes depuis le moniteur
void serialLecture()                                         // IDE monitor
{
	if (Serial.available())
	{
		cmdmonCmd = Serial.readStringUntil('\n');
		cmdmonCmd.trim();     // Nettoyage de la chaîne "' ' \r \n)
		cmdmonNew  = true;
	}
}

//------------------------------------- Réception de commandes depuis le moniteur
void btSerialLecture()                                         // IDE monitor
{
	if (btSerial.available())
	{
		btCmd = btSerial.readStringUntil('\n');
		btCmd.trim();     // Nettoyage de la chaîne "' ' \r \n)
		btCmdNew = true;
	}
}
//---------------------------------------------------------------------------------------
// Diverses routines pour faciliter l'usage de l'affichage LCD
//---------------------------------------------------------------------------------------
//---------------------- Effacement de la ligne rowNum
void lcdClsRow(int rowNum)
{
	lcdPrint(lcdEmptyLine, 0, rowNum);
}
//---------------------- Afficher texte Colonne Ligne
void lcdPrint(String lcdText, int lcdCol,int lcdRow)
{
	lcd.setCursor(lcdCol,lcdRow);
	lcd.print(lcdText);
}
//---------------------- Afficher texte de longueure d?termin?e
void lcdPrintLength(String lcdText, int lcdCol,int lcdRow, int textLength)
{
	String textToLength = lcdText + lcdEmptyLine;
	textToLength = textToLength.substring(0,textLength);
	
	lcdPrint(textToLength, lcdCol, lcdRow);
}

A ta disposition pour toutes questions.

Cordialement
jpbbricole

Merci bien ça me sera d’une très grande utilité

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.