пʼятницю, 26 січня 2018 р.

STM32: Бібліотека сенсору освітлення TSL2561 шина I2C

Передмова

Переробив бібліотеку з SparkFun TSL2561 library що для Arduino IDE на бібліотеку для STM32 використовуючи HAL Driver в роботі з I2C, все інше стандартний код Сі.

Датчик світла TSL2561 є світло-цифровими перетворювачем, який перетворює інтенсивність світла в цифровий вид. Керування по шині I2C TSL2561. Пристрій поєднує в собі один широкосмуговий фотодіод (видимий плюс інфрачервоний) та один інфрачервоний фотодіод на єдиній інтегрованій схемі CMOS. Два інтегрованих АЦП перетворюють фотодіодні потоки до цифрового виду. Ці цифрові данні можуть бути введені в мікропроцесор де вже визначається освітленість (рівень освітлення) у люксах використовуючи емпіричну формулу для наближення реакції людини на очі.

Що потрібно


  • Плата STM32F103RB Nucleo;
  • Сенсор TSL2561;
  • два резистори 10К для підтяжки шини I2C;
  • чотири дроти для з'єднання.

Зручність цієї плати в тім, що данні з сенсору можна передавати до термінальної програми на ПК по USART2 штатним засобом, без додаткового обладнання і дротів. Приєднавши до ПК плату STM32F103RB Nucleo USB шнурком отримуєте ST-LinkV2, Flash disk, UART (COM port) в одному флаконі. 
Сенсор освітлення приєднаємо до шини I2C2 MCU. Під'єднаємо два резистори для підтяжки SDA і SCL до логічної 1 (+Vcc живлення). І напишемо програму яка буде виводити в послідовний порт USART2 данні про освітлення.

Схема підключення

Схема підключення сенсора по I2C
На малюнку зображений сенсор BMP180, але це не має значення, головне показано як підключити до I2C шини. З TSL2561 все так само.

Створюємо проект в CubeMX

Створюємо новий проект в програмі CubeMX, обираємо свій MCU, назначаємо потрібні інтерфейси - SYS, I2C, USART, як на малюнку:
Налаштування шпильок
Даємо ім'я проекту, наприклад "STM32F103RB_I2C_UART_TSL2561", обираємо засіб розробки, наприклад "Atolic True Studio", та генеруємо код. З CubeMX це все.

Додаємо бібліотеку до проекту і пишемо тестову програму

Відкриваємо/експортуємо підготовлений, програмою CubeMX, проект в своєму засобі розробки.

Бібліотеку TSL2561 можна завантажити тут. Просто додайте заголовний файл бібліотеки "tsl2561.h" до теки "inc" проекту, а сирцевий файл бібліотеки "tsl2561.с" додайте до теки "src" проекту. З додаванням бібліотеки це все.

Відкриваємо головний файл проекту "main.c". І пишемо там такий код, у визначених ділянках для користувача програмою CubeMX.

Додаємо потрібні бібліотеки:
/* USER CODE BEGIN Includes */
#include "tsl2561.h"
#include <string.h>
#include <stdlib.h>
/* USER CODE END Includes */

Оголошуємо прототип функції друку текстових рядків до USART:
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
void print(char string[]);
/* USER CODE END PV */

Оголошуємо декілька змінних:
/* USER CODE BEGIN 1 */
 bool gain;        // Gain setting, 0 = X1, 1 = X16;
 unsigned int ms;  // Integration ("shutter") time in milliseconds
  /* USER CODE END 1 */

Друкуємо в послідовний порт USART текст, читаємо ID сенсору, ініціалізуємо сенсор та вмикаємо його:
/* USER CODE BEGIN 2 */
  print("\r\nUSART2 is OK\r\n");

  unsigned char ID;

  if (TSL2561_getID(&ID))
  {
   char string[2];
   sprintf(string, "%x", ID);

      print("Got factory ID: 0X");
      print(", should be 0X5X\r\n");
  }
  else
  {
     print("error get ID\r\n");
  }

  gain = 0;
  unsigned char time = 2;

  TSL2561_setTiming_ms(gain, time, &ms);
  TSL2561_setPowerUp();
  /* USER CODE END 2 */

В безкінечному циклі раз на секунду читаємо значення регістрів сенсору і вираховуємо значення "lux", та друкуємо все в послідовний порт:
/* USER CODE BEGIN WHILE */
  while (1)
  {
   char string[100];
   unsigned int data0, data1;

   if (TSL2561_getData(&data0, &data1))
   {
    double lux;    // Resulting lux value
    bool good;  // True if neither sensor is saturated

    // Perform lux calculation:
    good = TSL2561_getLux(gain, ms, data0, data1, &lux);

    // Print out the results:
    print("Data0: ");
    sprintf(string, "%d", data0);
    print(string);
    print(" -> ");
    print("Data1: ");
    sprintf(string, "%d", data1);
    print(string);
    print(" -> ");
    print("Lux: ");
    itoa((int) lux, string, 10);
    print(string);
    if (good) print(" (good)\r\n"); else print(" (BAD)\r\n");
  }
  else
  {
   // getData() returned false because of an I2C error, inform the user.
   print("error get lux\r\n");

  }
   HAL_Delay(1000);
  /* USER CODE END WHILE */

Не забуваймо додати саму функцію "print", прототип якої ми оголосили на початку програми:

/* USER CODE BEGIN 4 */
void print(char string[])
{
 HAL_UART_Transmit(&huart2, (uint8_t*) string, strlen(string), 100);
}
/* USER CODE END 4 */

Результат

Компілюємо програму, заливаємо готову прошивку до MCU, в термінальній програмі на ПК спостерігаємо результат:
Приклад роботи

Файли

Немає коментарів:

Дописати коментар