daily pastebin goal
1%
SHARE
TWEET

power_monitor.c

tmax Feb 9th, 2019 65 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "power_monitor.h"
  2. #include "esp_system.h"
  3. #include "freertos/FreeRTOS.h"
  4. #include "driver/i2c.h"
  5. #include "config.h"
  6. #include "esp_timer.h"
  7. #include "esp_log.h"
  8.  
  9. static const char* TAG = "power";
  10.  
  11. // Task
  12. static StackType_t stack[POWER_MONITOR_STACK_SIZE];
  13. static StaticTask_t task;
  14. static TaskHandle_t task_handle;
  15.  
  16. // I2C
  17. static i2c_config_t pic16_i2c_config;
  18.  
  19. // Data
  20. static power_status_t power_status;
  21.  
  22. // ISR will be executed on a falling edge from SDA
  23. static void IRAM_ATTR scl_isr_handler(void* arg)
  24. {
  25.     static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  26.  
  27.     if(!gpio_get_level(SCL_PIC16_PIN))
  28.     {
  29.         // Notify the task to start the I2C transmission
  30.         vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);
  31.  
  32.         if(xHigherPriorityTaskWoken)
  33.         {
  34.             portYIELD_FROM_ISR();
  35.         }
  36.     }
  37.  
  38.     // FAILED!
  39. }
  40.  
  41. static void power_monitor_task(void* args)
  42. {
  43.     uint8_t data[10] = {0};
  44.     esp_err_t err = ESP_OK;
  45.  
  46.     while(true)
  47.     {
  48.         // Wait forever for a notification, if we were notified then SCL went low
  49.         //  and we should start the I2C transmission now
  50.         if(ulTaskNotifyTake(pdTRUE, portMAX_DELAY))
  51.         {
  52.             // Read the data from the PIC16. Disable interrupts first so they are not fired
  53.             //  by the I2C activity
  54.             gpio_intr_disable(SCL_PIC16_PIN);
  55.            
  56.             // The command has to be re-created every time, yes, not the best but that's what we have
  57.             i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  58.             i2c_master_start(cmd);
  59.             i2c_master_write_byte(cmd, POWER_MONITOR_PIC16_ADDRESS | 0x01, true);
  60.             i2c_master_read(cmd, data, 10, I2C_MASTER_LAST_NACK);
  61.             i2c_master_stop(cmd);
  62.  
  63.             err = i2c_master_cmd_begin(PIC16_I2C_NUMBER, cmd, pdMS_TO_TICKS(20));
  64.             i2c_cmd_link_delete(cmd);
  65.  
  66.             gpio_intr_enable(SCL_PIC16_PIN);
  67.  
  68.             if(err != ESP_OK)
  69.             {
  70.                 ESP_LOGW(TAG, "Error reading");
  71.             }
  72.             else
  73.             {
  74.                 power_status.raw_3v3_v = ((uint16_t)data[0] << 8) | (uint16_t)data[1];
  75.                 power_status.raw_5v_v = ((uint16_t)data[2] << 8) | (uint16_t)data[3];
  76.                 power_status.raw_3v3_i = ((uint16_t)data[4] << 8) | (uint16_t)data[5];
  77.                 power_status.raw_5v_i = ((uint16_t)data[6] << 8) | (uint16_t)data[7];
  78.                 power_status.raw_bat_i = ((uint16_t)data[8] << 8) | (uint16_t)data[9];
  79.                 ESP_LOGV(TAG, "3.3V V: %d", power_status.raw_3v3_v/13);
  80.                 ESP_LOGV(TAG, "5V V: %d", power_status.raw_5v_v/13);
  81.                 ESP_LOGV(TAG, "3.3V I: %d", power_status.raw_3v3_i/13);
  82.                 ESP_LOGV(TAG, "5V I: %d", power_status.raw_5v_i/13);
  83.                 ESP_LOGV(TAG, "BAT I: %d", power_status.raw_bat_i/13);
  84.             }
  85.         }
  86.         else
  87.         {
  88.             ESP_LOGE(TAG, "Timeout should never occur");
  89.         }
  90.     }
  91. }
  92.  
  93. esp_err_t power_monitor_init(void)
  94. {
  95.     esp_err_t err;
  96.  
  97.     ESP_LOGI(TAG, "Initializing");
  98.  
  99.     // Set I2C bus for the PIC16 at 400 kHz. At startup start with I2C disabled
  100.     pic16_i2c_config.mode = I2C_MODE_MASTER;
  101.     pic16_i2c_config.sda_io_num = SDA_PIC16_PIN;
  102.     pic16_i2c_config.sda_pullup_en = GPIO_PULLUP_DISABLE;
  103.     pic16_i2c_config.scl_io_num = SCL_PIC16_PIN;
  104.     pic16_i2c_config.scl_pullup_en = GPIO_PULLUP_DISABLE;
  105.     pic16_i2c_config.master.clk_speed = 400000;
  106.  
  107.     // Setup I2C
  108.     if((err = i2c_param_config(PIC16_I2C_NUMBER, &pic16_i2c_config)) != ESP_OK)
  109.     {
  110.         ESP_LOGE(TAG, "Error setting up I2C");
  111.         return err;
  112.     }
  113.  
  114.     // Install I2C driver
  115.     if((err = i2c_driver_install(PIC16_I2C_NUMBER, pic16_i2c_config.mode, 0, 0, 0)) != ESP_OK)
  116.     {
  117.         ESP_LOGE(TAG, "Error installing I2C driver");
  118.         return err;
  119.     }
  120.  
  121.     // Set SDA and SCL pins as inputs and enable interrupt so we can detect when the PIC16
  122.     //  brings them low to alert us that new data is available.
  123.     gpio_config_t config;
  124.     config.pin_bit_mask = (1 << SDA_PIC16_PIN);
  125.     config.mode = GPIO_MODE_DEF_INPUT;
  126.     config.pull_up_en = GPIO_PULLUP_DISABLE;
  127.     config.pull_down_en = GPIO_PULLDOWN_DISABLE;
  128.     config.intr_type = GPIO_INTR_DISABLE;
  129.     if((err = gpio_config(&config)) != ESP_OK)
  130.     {
  131.         ESP_LOGE(TAG, "Error configuring SDA pin");
  132.         return err;
  133.     }
  134.  
  135.     config.pin_bit_mask = (1 << SCL_PIC16_PIN);
  136.     config.mode = GPIO_MODE_DEF_INPUT;
  137.     config.pull_up_en = GPIO_PULLUP_DISABLE;
  138.     config.pull_down_en = GPIO_PULLDOWN_DISABLE;
  139.     config.intr_type = GPIO_INTR_NEGEDGE;
  140.     if((err = gpio_config(&config)) != ESP_OK)
  141.     {
  142.         ESP_LOGE(TAG, "Error configuring SCL pin");
  143.         return err;
  144.     }
  145.  
  146.     // Task
  147.     task_handle = xTaskCreateStaticPinnedToCore(power_monitor_task, "power", POWER_MONITOR_STACK_SIZE,
  148.         NULL, POWER_MONITOR_TASK_PRIORITY, stack, &task, POWER_MONITOR_AFFINITY);
  149.  
  150.     // Add SDA isr callback
  151.     if((err = gpio_isr_handler_add(SCL_PIC16_PIN, scl_isr_handler, 0)) != ESP_OK)
  152.     {
  153.         ESP_LOGE(TAG, "Error setting ISR handler");
  154.         return err;
  155.     }
  156.  
  157.     ESP_LOGI(TAG, "Ready!");
  158.     return ESP_OK;
  159. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top