Skip to content
Snippets Groups Projects
Select Git revision
  • 7daa1b260baa6e631823016abe9e1aa4713346c1
  • main default protected
  • master
3 results

Display.class

Blame
  • Forked from LABOUREL Arnaud / Image Template
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    main.c 9.77 KiB
    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/uuid.h>
    //#################################################
    #include <zephyr/drivers/adc.h>
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <stdint.h>
    //------------------------------------------------
    //------------------------------------------------
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/sensor.h>
    //------------------------------------------------
    //------------------------------------------------
    
    
    /* ADC node from the devicetree. */
    #define ADC_NODE DT_ALIAS(adc0)
    
    /* Data of ADC device specified in devicetree. */
    static const struct device *adc = DEVICE_DT_GET(ADC_NODE);
    
    /* Configuration of the ADC channel */
    static const struct adc_channel_cfg channel_cfg = {
        .gain = ADC_GAIN_1_6,
        .reference = ADC_REF_INTERNAL,
        .acquisition_time = ADC_ACQ_TIME_DEFAULT,
        .channel_id = 0,
        .input_positive = SAADC_CH_PSELP_PSELP_VDD,
    };
    
    #define ADC_RESOLUTION 12
    #define BUFFER_SIZE 1 /* We only need one sample */
    
    static int16_t sample_buffer[BUFFER_SIZE];
    
    //#################################################
    
    #define SERVICE_DATA_LEN        15
    #define SERVICE_UUID            0xfcd2      /* BTHome service UUID */
    #define IDX_TEMPL               4           /* Index of lo byte of temp in service data*/
    #define IDX_TEMPH               5           /* Index of hi byte of temp in service data*/
    #define IDX_HUML 				7 			/* Index of lo byte of humidity in service data */
    #define IDX_HUMH 				8			/* Index of hi byte of humidity in service data */
    #define IDX_PRESL      			10         	/* Index of lo byte of pressure in service data (in hPa */                                               
    #define IDX_PRESM				11 			/* Index of hi byte of pressure in service data (in hPa)*/
    #define IDX_PRESH 				12 			/* Index of hi byte of pressure in service data (in hPa) */
    #define BAT              	 	14          /* Index of hi byte of temp in service data*/
    
    
    #define ADV_PARAM BT_LE_ADV_PARAM(BT_LE_ADV_OPT_USE_IDENTITY, \
    				  BT_GAP_ADV_SLOW_INT_MIN, \
    				  BT_GAP_ADV_SLOW_INT_MAX, NULL)
    
    
    static uint8_t service_data[SERVICE_DATA_LEN] = {
    	BT_UUID_16_ENCODE(SERVICE_UUID),
    	0x40,
    	0x02,	/* Temperature */
    	0xc4,	/* Low byte */
    	0x00,   /* High byte */
    	0x03,	/* Humidity */
    	0xbf,	/* 50.55%  low byte*/
    	0x13,   /* 50.55%  high byte*/
    	0x04, /* Pressure type identifier*/
        0x00, /* Low byte of pressure */
        0x00, /* Middle byte of pressure */
        0x00,  /* High byte of pressure */
    	0x01,	/* BATTERY */
    	0x80,
    
    };
    
    static struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
    	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
    	BT_DATA(BT_DATA_SVC_DATA16, service_data, ARRAY_SIZE(service_data))
    };
    
    static void bt_ready(int err)
    {
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    
    	printk("Bluetooth initialized\n");
    
    	/* Start advertising */
    	err = bt_le_adv_start(ADV_PARAM, ad, ARRAY_SIZE(ad), NULL, 0);
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
    }
    
    ////////////////////////////////////////////////////////////
    double get_Tension(int32_t adc_value) {
        // Le gain est toujours égal à 1/6
        double gain = 1.0 / 6.0;
        double vref = 0.6;
    
        // Calcul de la tension en utilisant l'équation donnée
        double tension = ( (adc_value * vref) / ( 4095 * gain) );
        return tension;
    }
    
    double calculer_capacite_restante_NiMH_2_cells(double tension_batterie) {
        double capacite_restante;
    
        // La tension de la batterie est de 2.0V à 2.7V pour 2 cellules NiMH en série
        if (tension_batterie >= 2.7) {
            capacite_restante = (tension_batterie - 2.7) * (100 - 90) / (2.8 - 2.7) + 90;  // Plage 2.7V - 2.8V
        } else if (tension_batterie >= 2.6) {
            capacite_restante = (tension_batterie - 2.6) * (90 - 80) / (2.7 - 2.6) + 80;  // Plage 2.6V - 2.7V
        } else if (tension_batterie >= 2.5) {
            capacite_restante = (tension_batterie - 2.5) * (80 - 70) / (2.6 - 2.5) + 70;  // Plage 2.5V - 2.6V
        } else if (tension_batterie >= 2.4) {
            capacite_restante = (tension_batterie - 2.4) * (70 - 60) / (2.5 - 2.4) + 60;  // Plage 2.4V - 2.5V
        } else if (tension_batterie >= 2.3) {
            capacite_restante = (tension_batterie - 2.3) * (60 - 50) / (2.4 - 2.3) + 50;  // Plage 2.3V - 2.4V
        } else if (tension_batterie >= 2.2) {
            capacite_restante = (tension_batterie - 2.2) * (50 - 40) / (2.3 - 2.2) + 40;  // Plage 2.2V - 2.3V
        } else if (tension_batterie >= 2.1) {
            capacite_restante = (tension_batterie - 2.1) * (40 - 30) / (2.2 - 2.1) + 30;  // Plage 2.1V - 2.2V
        } else if (tension_batterie >= 2.0) {
            capacite_restante = (tension_batterie - 2.0) * (30 - 20) / (2.1 - 2.0) + 20;  // Plage 2.0V - 2.1V
        } else {
            capacite_restante = 0;  // Moins de 10% de charge
        }
    
        return capacite_restante;
    }
    ////////////////////////////////////////////////////////////
    //--------------------------------------------------
    //--------------------------------------------------
    static const struct device *get_bme280_device(void) {
      const struct device *const dev = DEVICE_DT_GET_ANY(bosch_bme280);
    
      if (dev == NULL) {
        /* No such node, or the node does not have status "okay". */
        printk("\nError: no device found.\n");
        return NULL;
      }
    
      if (!device_is_ready(dev)) {
        printk("\nError: Device \"%s\" is not ready; "
               "check the driver initialization logs for errors.\n",
               dev->name);
        return NULL;
      }
    
      printk("Found device \"%s\", getting sensor data\n", dev->name);
      return dev;
    }
    //--------------------------------------------------
    //--------------------------------------------------
    
    
    int main(void)
    {
    	int err;
    	const struct device *dev = get_bme280_device();
    	struct sensor_value temp, humidity, press;
    
    	//#################################################
    	printk("Starting BTHome sensor template\n");
    
    	/* Initialize the Bluetooth Subsystem */
    	err = bt_enable(bt_ready);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    
    
        /* Configure the sampling sequence */
        struct adc_sequence sequence = {
            .channels = BIT(channel_cfg.channel_id),
            .buffer = sample_buffer,
            .buffer_size = sizeof(sample_buffer),
            .resolution = ADC_RESOLUTION,
        };
    
    	//#################################################
    
    	if (!device_is_ready(adc)) {
    		printf("ADC controller device %s not ready\n", adc->name);
    		return 0;
    	}
    
    	err = adc_channel_setup(adc, &channel_cfg);
    	if (err < 0) {
            printf("Could not setup ADC channel (%d)\n", err);
    		return 0;
    	}
    //#################################################
    
    
    	for (;;) {
    //#################################################
    		// Récupération des échantillons du capteur
    		if (sensor_sample_fetch(dev) < 0) {
    			printk("Erreur lors de la récupération des données du capteur\n");
    			continue;
    		}
    
    		err = adc_read(adc, &sequence);
    		if (err < 0) {
    			printf("Could not read (%d)\n", err);
    			continue;
    		}
    
    		// Récupération des différentes valeurs
    		sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
    		sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);
    		sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);
    
    
    		// Convertir la température en centi-degrés Celsius (°C * 100) en tenant
    		// compte de val2
        	int temperature_centi = (temp.val1 * 100) + (temp.val2 / 10000);
            int32_t val_mv = sample_buffer[0]; /* Read raw value */
    
    		// Mettre à jour les deux octets dans service_data pour la température
    		service_data[IDX_TEMPH] = (temperature_centi >> 8) & 0xff; // Partie haute
    		service_data[IDX_TEMPL] = temperature_centi & 0xff;        // Partie basse
    
    		// Convertir l'humidité en centi-pourcent (% * 100) en tenant compte de val2
    		int humidity_centi = (humidity.val1 * 100) + (humidity.val2 / 10000);
    
    		// Mettre à jour les deux octets dans service_data pour l'humidité
    		service_data[IDX_HUMH] = (humidity_centi >> 8) & 0xff; // Partie haute
    		service_data[IDX_HUML] = humidity_centi & 0xff;        // Partie basse
    
    		// Convertir la pression et la mettre à jour dans service_data
    		int pressure_hpa =
    			100*((press.val1 * 10) + (press.val2 / 10000)); // Convertir en hPa
    		service_data[IDX_PRESH] =
    			(pressure_hpa) >> 16; // Haute partie de la pression
    		service_data[IDX_PRESM] =
    			(pressure_hpa >> 8) & 0xff; // Partie intermédiaire
    		service_data[IDX_PRESL] =
    			(pressure_hpa)&0xff; // Basse partie de la pression
    
    		// Affichage des résultats avec les unités
    		printk("temp: %d.%06d°C; humidity: %d.%06d%%; press: %d hPa\n", temp.val1,
    			temp.val2, humidity.val1, humidity.val2, pressure_hpa);
    
    		// Mettre à jour les données de la publicité
    		err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), NULL, 0);
    		if (err) {
    		printk("Failed to update advertising data (err %d)\n", err);
    		}
    
    		err = adc_raw_to_millivolts(channel_cfg.reference,
    			channel_cfg.gain,
    			ADC_RESOLUTION, &val_mv);
    
    
    		/* Simulate temperature from 0C to 25C */
    		double battery_voltage =(get_Tension(sample_buffer[0]));
    				
    		service_data[BAT] = calculer_capacite_restante_NiMH_2_cells(battery_voltage);
    		//service_data[BAT_H] = (battery_voltage >> 8) & 0xff;
    		//service_data[BAT_L] = battery_voltage & 0xff;
    
    
    		if (err < 0 || channel_cfg.reference == 0) {
                printk("Raw value: %d (conversion to mV not available)\n", sample_buffer[0]);
            } else {
    			printk("Raw ADC value: %d\n", service_data[BAT]);
    
                printk("Battery voltage: %f \n", battery_voltage);
            }
    //#################################################
    
    		
    		
    
    		err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), NULL, 0);
    		if (err) {
    			printk("Failed to update advertising data (err %d)\n", err);
    		}
    		k_sleep(K_MSEC(BT_GAP_ADV_SLOW_INT_MIN));
    	}
    	return 0;
    }