В данной статье мы рассмотрим подключение датчика веса/нагрузки (Load cell) с модулем усиления HX711 к плате Raspberry Pi и создадим на их основе автоматические ворота. Наверняка вы уже видели во многих местах (торговые центры и т.д.) ворота (двери) с подсоединённым к ним датчиком веса, которые автоматически открываются когда кто-нибудь подойдет/станет рядом с ними и закрываются, когда человек пройдет ворота/дверь. В данном проекте мы рассмотрим создание подобных автоматических ворот на основе платы Raspberry Pi, которые будут "чувствовать" давление и открываться автоматически, при этом они будут оставаться открытыми до тех пор, пока давление (вес) будет действовать на датчик веса. Как только вес с датчика будет убираться ворота будут автоматически закрываться. Вместо датчика веса в подобных автоматических воротах можно использовать PIR датчик.
В демонстрационных целях в данном проекте в качестве ворот мы использовали электродвигатель постоянного тока, измеряемый вес мы будем класть на картонное основание. Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи. Также мы рассматривали работу с датчиком веса и модулем усиления HX711 в статье про их подключение к плате Arduino. Также на эту тематику можете посмотреть проект автоматических весов на основе платы Arduino.
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- Датчик веса (Load cell) (купить на AliExpress).
- Модуль усиления датчика веса HX711 (Load cell Amplifier Module) (купить на AliExpress).
- Микросхема драйвера двигателей L293D (купить на AliExpress).
- Электродвигатель постоянного тока или DVD привод.
- ЖК дисплей 16x2 (купить на AliExpress).
- Источник питания.
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Датчик веса и модуль усиления HX711
Датчик веса представляет собой полупроводник, который преобразует приложенные силу или давление в электрическое напряжение. Величина этого напряжения прямо пропорциональна приложенной к датчику силе. Датчик веса имеет измеритель деформации (strain gauge), который деформируется под действием приложенной силы (давления). Измеритель деформации генерирует электрический сигнал когда в результате деформации изменяется его эффективное сопротивление. Обычно датчик нагрузки состоит из 4-х измерителей деформации, объединенных по принципу моста Уитстона (моста для измерения сопротивления). Мы в нашем проекте будем использовать датчик нагрузки, способный измерять вес тел до 40 кг, однако производятся датчики нагрузки и с другим диапазоном измеряемых весов – до 5 кг, до 10 кг, до 100 кг и более.
Но электрические сигналы, генерируемые датчиком веса, весьма слабы – всего несколько милливольт. Поэтому перед их обработкой в плате Arduino они нуждаются в усилении – и для этой цели подходит модуль усиления датчика нагрузки HX711, показанный на нижеприведенном рисунке. Этот модуль содержит чип HX711, представляющий собой высокоточный 24-разрядный аналогово-цифровой преобразователь (АЦП). HX711 имеет два аналоговых входных канала, коэффициент усиления для которых можно программировать. Таким образом, модуль HX711 усиливает слабые электрические сигналы от датчика нагрузки и затем эти усиленные и оцифрованные сигналы подает на плату Arduino для их дальнейшей обработки (извлечения информации о весе).
Датчик нагрузки соединяется с модулем усиления HX711 с помощью 4 проводов: красного, черного, белого и зеленого/синего цвета. Возможны некоторые изменения цветовой гаммы этих проводов в зависимости от производителя модуля. Для соединения этих двух компонентов нашего устройства необходимо будет сделать следующие подключения как показано на ниже приведенном рисунке:
• красный провод - к E+;
• черный провод - к E-;
• белый провод - к A-;
• зеленый провод - к A+.
Фиксация датчика веса на основании
Этот этап вы можете пропустить и не использовать никакой платформы/основания, но лучше все таки его сделать для более удобной работы с датчиком веса. В "идеальных" автоматических воротах датчик веса должен располагаться прямо перед воротами чтобы он срабатывал когда человек подойдет к воротам (двери). Но в данном проекте в демонстрационных целях мы разместили датчик веса под жесткой картонной пластиной, которая служит в качестве платформы. Также датчик веса прикреплен к деревянному основанию с помощью болтов и гаек чтобы он оставался в неподвижном состоянии. На следующих рисунках представлен рассмотренный пример фиксации датчика веса.
Схема проекта
Схема подключения датчика веса с модулем усиления HX711 к плате Raspberry Pi представлена на следующем рисунке.
В представленной схеме контакты ЖК дисплея 16x2 RS, EN, d4, d5, d6 и d7 подключены к контактам 18, 23, 24, 25, 8 и 7 платы Raspberry Pi соответственно. Контакты DT и SCK модуля HX711 непосредственно подключены к контактам 27 и 17 платы Raspberry Pi, а драйвер двигателя L293D подключен к контактам 12 и 16 платы.
Объяснение работы проекта
В нашем проекте плата Raspberry Pi управляет всеми процессами в схеме. Датчик веса обнаруживает приложенное к нему усилие и передает электрический сигнал, пропорциональный измеренному весу, на модуль усиления датчика веса HX711. Модуль HX711 представляет собой 24-битный АЦП (аналого-цифровой преобразователь), который усиливает сигнал с выхода датчика веса и преобразует его в цифровую форму. Затем это цифровое значение подается на плату Raspberry Pi, которая сравнивает его с заранее установленным (опорным) значением веса и на основании результата этого сравнения управляет открытием/закрытием ворот с помощью микросхемы драйвера двигателя L293D. В качестве ворот мы использовали электродвигатель постоянного тока. Если же вы для этой цели используете DVD привод, то можете посмотреть следующий аналогичный проект – автоматическое открывание двери с помощью Arduino.
Структурная схема работы проекта показана на следующем рисунке.
В этом проекте в качестве опорного значения веса мы использовали вес равный 100 грамм, то есть если мы будем помещать на платформу вес больший 100 грамм, то ворота будут автоматически открываться. После удаления этого веса с платформы ворота будут автоматически закрываться. На экране ЖК дисплея будет отображаться состояние ворот – открыты/закрыты.
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
В этом проекте мы не использовали никаких библиотек для подключения датчика веса и модуля усиления HX711 к плате Raspberry Pi, мы полагались только на даташит на эти устройства. Но библиотеки для работы с датчиком веса для Raspberry Pi есть и если вы их будете использовать, то вам удастся уменьшить объем кода программы по сравнению с нашим вариантом.
Первым делом в программе мы должны подключить необходимые библиотеки, инициализировать необходимые переменные и контакты (к которым подключается ЖК дисплей, модуль HX711 и электродвигатель постоянного тока).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import RPi.GPIO as gpio import time RS =18 EN =23 D4 =24 D5 =25 D6 =8 D7 =7 DT =27 SCK=17 m1=12 m2=1 |
После этого мы запрограммируем функцию для считывания данных с модуля HX711.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def readCount(): i=0 Count=0 gpio.setup(DT, gpio.OUT) gpio.output(DT,1) gpio.output(SCK,0) gpio.setup(DT, gpio.IN) while gpio.input(DT) == 1: i=0 for i in range(24): gpio.output(SCK,1) Count=Count<<1 gpio.output(SCK,0) #time.sleep(0.001) if gpio.input(DT) == 0: Count=Count+1 gpio.output(SCK,1) Count=Count^0x800000 gpio.output(SCK,0) return Count |
Далее в основной функции (бесконечном цикле) нашей программы мы будем считывать данные о весе с модуля HX711 и сравнивать их с опорным значением веса, и в зависимости от результата сравнения принимать решение от открытии или закрытии ворот.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
while 1: count= readCount() w=0 w=(count-sample)/106 print w,"g" if w>100: setCursor(0,0) lcdprint("Gate Opened ") if flag == 0: gpio.output(m1, 1) gpio.output(m2, 0) time.sleep(1.3) gpio.output(m1, 0) gpio.output(m2, 0) time.sleep(1.5) flag=1; lcdclear() elif w<100: setCursor(0,0) lcdprint("Gate Closed ") if flag==1: gpio.output(m1, 0) gpio.output(m2, 1) time.sleep(1.3) gpio.output(m1, 0) gpio.output(m2, 0) time.sleep(2) flag=0 time.sleep(0.5) |
Также мы запрограммируем ряд функций для работы с ЖК дисплеем:
- def begin() – для инициализации ЖК дисплея;
- def lcdcmd(ch) – для передачи команд на ЖК дисплей;
- def lcdwrite(ch) – для вывода символа на экран ЖК дисплея;
- def lcdclear() – для очистки экрана ЖК дисплея;
- def lcdprint(Str) – для вывода строки на экран ЖК дисплея.
Коды всех этих функций приведены в полном тексте программы.
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
import RPi.GPIO as gpio import time RS =18 EN =23 D4 =24 D5 =25 D6 =8 D7 =7 DT =27 SCK=17 m1=12 m2=16 HIGH=1 LOW=0 sample=0 val=0 gpio.setwarnings(False) gpio.setmode(gpio.BCM) gpio.setup(RS, gpio.OUT) gpio.setup(EN, gpio.OUT) gpio.setup(D4, gpio.OUT) gpio.setup(D5, gpio.OUT) gpio.setup(D6, gpio.OUT) gpio.setup(D7, gpio.OUT) gpio.setup(m1, gpio.OUT) gpio.setup(m2, gpio.OUT) gpio.setup(SCK, gpio.OUT) gpio.output(m1 , 0) gpio.output(m2 , 0) def begin(): lcdcmd(0x33) lcdcmd(0x32) lcdcmd(0x06) lcdcmd(0x0C) lcdcmd(0x28) lcdcmd(0x01) time.sleep(0.0005) def lcdcmd(ch): gpio.output(RS, 0) gpio.output(D4, 0) gpio.output(D5, 0) gpio.output(D6, 0) gpio.output(D7, 0) if ch&0x10==0x10: gpio.output(D4, 1) if ch&0x20==0x20: gpio.output(D5, 1) if ch&0x40==0x40: gpio.output(D6, 1) if ch&0x80==0x80: gpio.output(D7, 1) gpio.output(EN, 1) time.sleep(0.005) gpio.output(EN, 0) # Low bits gpio.output(D4, 0) gpio.output(D5, 0) gpio.output(D6, 0) gpio.output(D7, 0) if ch&0x01==0x01: gpio.output(D4, 1) if ch&0x02==0x02: gpio.output(D5, 1) if ch&0x04==0x04: gpio.output(D6, 1) if ch&0x08==0x08: gpio.output(D7, 1) gpio.output(EN, 1) time.sleep(0.005) gpio.output(EN, 0) def lcdwrite(ch): gpio.output(RS, 1) gpio.output(D4, 0) gpio.output(D5, 0) gpio.output(D6, 0) gpio.output(D7, 0) if ch&0x10==0x10: gpio.output(D4, 1) if ch&0x20==0x20: gpio.output(D5, 1) if ch&0x40==0x40: gpio.output(D6, 1) if ch&0x80==0x80: gpio.output(D7, 1) gpio.output(EN, 1) time.sleep(0.005) gpio.output(EN, 0) # Low bits gpio.output(D4, 0) gpio.output(D5, 0) gpio.output(D6, 0) gpio.output(D7, 0) if ch&0x01==0x01: gpio.output(D4, 1) if ch&0x02==0x02: gpio.output(D5, 1) if ch&0x04==0x04: gpio.output(D6, 1) if ch&0x08==0x08: gpio.output(D7, 1) gpio.output(EN, 1) time.sleep(0.005) gpio.output(EN, 0) def lcdclear(): lcdcmd(0x01) def lcdprint(Str): l=0; l=len(Str) for i in range(l): lcdwrite(ord(Str[i])) def setCursor(x,y): if y == 0: n=128+x elif y == 1: n=192+x lcdcmd(n) def readCount(): i=0 Count=0 # print Count # time.sleep(0.001) gpio.setup(DT, gpio.OUT) gpio.output(DT,1) gpio.output(SCK,0) gpio.setup(DT, gpio.IN) while gpio.input(DT) == 1: i=0 for i in range(24): gpio.output(SCK,1) Count=Count<<1 gpio.output(SCK,0) #time.sleep(0.001) if gpio.input(DT) == 0: Count=Count+1 #print Count gpio.output(SCK,1) Count=Count^0x800000 #time.sleep(0.001) gpio.output(SCK,0) return Count begin() lcdcmd(0x01) lcdprint(" Automatic Gate ") lcdcmd(0xc0) lcdprint(" Using RPI ") time.sleep(3) lcdcmd(0x01) lcdprint("Circuit Digest") lcdcmd(0xc0) lcdprint("Welcomes You") time.sleep(3) sample= readCount() flag=0 lcdclear() while 1: count= readCount() w=0 w=(count-sample)/106 print w,"g" if w>100: setCursor(0,0) lcdprint("Gate Opened ") if flag == 0: gpio.output(m1, 1) gpio.output(m2, 0) time.sleep(1.3) gpio.output(m1, 0) gpio.output(m2, 0) time.sleep(1.5) flag=1; lcdclear() elif w<100: setCursor(0,0) lcdprint("Gate Closed ") if flag==1: gpio.output(m1, 0) gpio.output(m2, 1) time.sleep(1.3) gpio.output(m1, 0) gpio.output(m2, 0) time.sleep(2) flag=0 time.sleep(0.5) |