Skip to content

Sonde météo ESP32 sur MQTT avec une sonde de type PT100

Objectif

Le but de ce projet est de créer une sonde météo qui envoie ses données sur un broker MQTT.

Il fallait concevoir le conditionnement du signal de la sonde PT100 à 3 fils, et le code de l'ESP32. J'ai également développé une application cliente MQTT en Swift pour recevoir les données et les afficher sur un téléphone.

Réalisation

Conditionnement du signal

Nous avons utilisé un montage à courant constant pour conditionner le signal de la sonde PT100. Le montage est le suivant :

  • Un générateur de courant LM334 qui permet de générer un courant constant de 1mA
  • Un amplificateur d'instrumentation AD623 qui permet de mesurer et d'amplifier le signal de la sonde PT100

Nous avons aussi expérimenté un montage à pont de Wheatstone.

Simulation PSIM

Simulation PSIM

ESP32 et MQTT

Une fois la mesure faite, il fallait envoyer la température mesurée sur un broker MQTT, dans un certain topic. Pour cela, j'ai utilisé la bibliothèque Adafruit_MQTT. J'ai dû installer un broker MQTT sur un serveur pour pouvoir tester le code, j'ai donc utilisé Mosquitto.

cpp
Adafruit_MQTT_Publish test = Adafruit_MQTT_Publish(&mqtt, "/temperature");

Application iOS

Cette application n'était pas demandée dans le projet, mais je l'ai développée pour pouvoir visualiser les données envoyées par l'ESP32. J'ai utilisé le framework CocoaMQTT, qui est un client MQTT en Swift. L'application est conçue en SwiftUI.

CocoaMQTT

Il a fallu créer un ViewModel (héritant CocoaMQTTDelegate), qui permet de gérer les événements MQTT, et de mettre à jour les données de l'application.

Cliquer pour afficher le code du ViewModel
swift
class MQTTViewModel: ObservableObject, CocoaMQTTDelegate {
	@Published var state: ConnectionState
	@Published var temperature: String
	@Published var error: String?
	@Published var error2: String?


	@Published var MQTTUser: String = "rw"
	@Published var MQTTPassword: String = "readwrite"
	@Published var MQTTTLS: Bool = false


	var mqtt: CocoaMQTT

	init() {
		self.state = .unconnected
		self.temperature = "..."
		self.mqtt = CocoaMQTT(clientID: "CocoaMQTT-" + String(ProcessInfo().processIdentifier), host: "test.mosquitto.org", port: 1884)
	}

	func mqttSettings() {
		mqtt.username = MQTTUser
		mqtt.password = MQTTPassword
		mqtt.keepAlive = 60
		mqtt.enableSSL = MQTTTLS
		mqtt.delegate = self
		_ = mqtt.connect()
		print(self.self)
		print(mqtt.clientID)
	}

	func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
		print("ack: \(ack)")

		switch(ack) {

		case .accept:
			mqtt.subscribe("/temperature", qos: CocoaMQTTQoS.qos1)
			self.state = .connected
			self.mqtt = mqtt
			self.error = nil
			break

		case .unacceptableProtocolVersion:
			self.error2 = ack.description
		case .identifierRejected:
			self.error2 = ack.description
		case .serverUnavailable:
			self.error = "Serveur non disponible"
		case .badUsernameOrPassword:
			self.error2 = "Mauvais utilisateur ou mot de passe"
		case .notAuthorized:
			self.error2 = "Non autorisé"
		case .reserved:
			self.error2 = ack.description
		}

		if ack == .accept {
			//chatViewController?.mqttVersion = mqttVesion
			//navigationController!.pushViewController(chatViewController!, animated: true)
		}

	}


	func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {

	}

	func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {

	}

	func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) {
		if let msg = message.string {
			print(msg)
			UINotificationFeedbackGenerator().notificationOccurred(.success)
			if let temperature = Double(msg) {
				self.temperature = String(format: "%.1f", temperature)
			} else {
				self.temperature = msg
			}
		} else {
			print(message)
		}
	}

	func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) {
		print("did subscribe to topics:")
		print(success)
        if failed.count > 0 {
            print("failed to subscribe to topics:")
            print(failed)
        }
	}

	func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) {
	}

	func mqttDidPing(_ mqtt: CocoaMQTT) {
	}

	func mqttDidReceivePong(_ mqtt: CocoaMQTT) {
	}

	func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) {
		if let msg = err?.localizedDescription {
			print("Error: \(msg)")
			self.error = msg
			UINotificationFeedbackGenerator().notificationOccurred(.error)
		}
		self.state = .disconnected
	}


}