tag:blogger.com,1999:blog-53459400227232926312024-03-14T03:13:34.325-07:00Just for duinoMisha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.comBlogger54125tag:blogger.com,1999:blog-5345940022723292631.post-75929431260226514962020-12-10T11:01:00.000-08:002020-12-10T11:01:09.373-08:00Нейронная сеть. Часть 3.<p>Снова делаю побитовое И.</p><a name='more'></a>
<p>На этот раз функцией активации будет parametric rectified linear unit (PReLU).</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoMUjlxedZjzY4003dIjSf7v3VImcYd54md82cO-3BzZrRvOjKutRw1DPoFLm9VjI858EsDlMdcEw4URRU1MlQeaIgwFaKpm908QVYij5NTMjlA-CvrBn93zxaJfDC8LuMdG14AQC_2r4N/s803/prelu_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="803" data-original-width="803" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoMUjlxedZjzY4003dIjSf7v3VImcYd54md82cO-3BzZrRvOjKutRw1DPoFLm9VjI858EsDlMdcEw4URRU1MlQeaIgwFaKpm908QVYij5NTMjlA-CvrBn93zxaJfDC8LuMdG14AQC_2r4N/w400-h400/prelu_1.png" width="400" /></a></div>
<p>По сути, PReLU состоит из двух линейных функций y = a * x. У первой функции множитель a = 0.1 (для x < 0). У второй функции множитель a = 1.0 (для x >= 0). Это один из возможных вариантов. А вариантов не мало.</p>
<p>Код</p>
<pre style="background-color: #232629; color: #cfcfc2;"><b>def</b> activation_function (<span style="color: #27aeae;">self</span>, x) :
<span style="color: #7a7c7d;">"""PReLU</span>
<span style="color: #7a7c7d;"> """</span>
<b><span style="color: #fdbc4b;">if</span></b> x < <span style="color: #f67400;">0</span> :
<b><span style="color: #fdbc4b;">return</span></b> (<span style="color: #f67400;">0.1</span> * x)
<b><span style="color: #fdbc4b;">return</span></b> (x)</pre>
<p>И опять изменение функции активации это единственное изменение в коде сетей (полностью код нейронных сетей показан в первой статье).</p>
<p>Первая нейронная сеть</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-ko5U90qanS-v7Qdnt6lA1fGwTcGPlALCllzWddv3dyHCrcl6KxBgJcWwQyEpHrL4LJFmMnu6d8yvG_kbsq22ZWCKIuoBobBXcJERFvepzWlPpKoLr5z3soQa4FvT8tRQhQDv4ir0MoPW/s850/and_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="850" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-ko5U90qanS-v7Qdnt6lA1fGwTcGPlALCllzWddv3dyHCrcl6KxBgJcWwQyEpHrL4LJFmMnu6d8yvG_kbsq22ZWCKIuoBobBXcJERFvepzWlPpKoLr5z3soQa4FvT8tRQhQDv4ir0MoPW/w400-h376/and_3.png" width="400" /></a></div>
<p>w0 = 0.4<br />
w1 = 0.4</p>
<p>Результат выполнения кода</p>
<p>$ python3 ./and_3_prelu.py<br />
0.1 0.1 0.08<br />
0.1 0.9 0.40<br />
0.9 0.1 0.40<br />
0.9 0.9 0.72</p>
<p>Похожий результат был у сети с линейной функцией активации.</p>
<p>Вторая нейронная сеть</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYwqn-uRdVAO9xlA_jpTayUytqgZJ2L_8G-FxGCKM591XSC15N6ovUMJehWmzDiSBSSxPeir1foXZ3Kg3XTeqgBqKXeRFHuwy3aPc-rExk1vwpTsFeo-R8h86FJNIRhU8HOvPMTY6clTgY/s1200/and_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYwqn-uRdVAO9xlA_jpTayUytqgZJ2L_8G-FxGCKM591XSC15N6ovUMJehWmzDiSBSSxPeir1foXZ3Kg3XTeqgBqKXeRFHuwy3aPc-rExk1vwpTsFeo-R8h86FJNIRhU8HOvPMTY6clTgY/w400-h266/and_5.png" width="400" /></a></div>
<p>w0 = -0.5<br />
w1 = 4.6<br />
w2 = -0.7<br />
w3 = 2.4<br />
w4 = 1.2<br />
w5 = -2.3</p>
<p>Результат выполнения кода</p>
<p>$ python3 ./and_5_prelu.py<br />
0.1 0.1 0.10099999999999998<br />
0.1 0.9 0.10099999999999909<br />
0.9 0.1 0.10169999999999996<br />
0.9 0.9 0.9089999999999989</p>
<p>Такой же результат был получен на сети с логистической функцией активации.</p>
<p>Третья нейронная сеть</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPGpIu4HS1toy0Q9qhRsGXA87D7wUYXNI2nmZqFPks_MvYbQ2e5RLhPCJ5cq4zdW7wSxDU1Ds0g70iWTi6T0fINZwvb4NtegPAMtdA530uhd-3m6-UV8samLRtwDtIXLkCLMhdZpZscqDS/s1200/and_6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPGpIu4HS1toy0Q9qhRsGXA87D7wUYXNI2nmZqFPks_MvYbQ2e5RLhPCJ5cq4zdW7wSxDU1Ds0g70iWTi6T0fINZwvb4NtegPAMtdA530uhd-3m6-UV8samLRtwDtIXLkCLMhdZpZscqDS/w400-h266/and_6.png" width="400" /></a></div>
<p>w0 = 0.8<br />
w1 = 1.7<br />
w2 = 5.0<br />
w3 = -2.2<br />
w4 = 4.4<br />
w5 = 4.2<br />
w6 = -3.4<br />
w7 = -0.6<br />
w8 = 1.3</p>
<p>Результат выполнения кода</p>
<p>$ python3 ./and_6_prelu.py<br />
[0.1, 0.1] [0.10000000000000009]<br />
[0.1, 0.9] [0.10080000000000044]<br />
[0.9, 0.1] [0.10000000000000053]<br />
[0.9, 0.9] [0.9000000000000021]</p>
<p>Ожидаемый результат.</p>
<p>Итак. Сеть с функцией активации PReLU похожа на сеть с логистической функцией. Зачем тогда вообще нужна PReLU? Одним из достоинств PReLU является скорость работы. PReLU существенно быстрее логистической функции. А чем быстрее функция активации, тем быстрее работает нейронная сеть. И обучение быстрой сети требует меньше времени.</p>Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-16924170883553593802020-12-08T09:49:00.001-08:002020-12-10T11:10:21.984-08:00Нейронная сеть. Часть 2.<p>Продолжаю делать побитовое И на нейронных сетях.</p><a name='more'></a>
<p>Теперь в нейронах сетей будет применяться логистическая функция активации.</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRiQptAsxcu3DYNFad-26NBmnKRkPeUNr21xiob44NF5aiFGloiXvwnAkLFrA-DqtVAZ1Wo3H7rgr9nouesOKoNlvL0SBTpDDs4wKVmrwM2vCCjXfSC8j4BbV3062ZIIgcb84ABpvYk9oN/s803/logistic_1.png" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="803" data-original-width="803" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRiQptAsxcu3DYNFad-26NBmnKRkPeUNr21xiob44NF5aiFGloiXvwnAkLFrA-DqtVAZ1Wo3H7rgr9nouesOKoNlvL0SBTpDDs4wKVmrwM2vCCjXfSC8j4BbV3062ZIIgcb84ABpvYk9oN/w400-h400/logistic_1.png" width="400" /></a></div>
<p>y = 1.0 / (1.0 + (e ** (-1.0 * x)))</p>
<p>Код</p>
<pre style="background-color: #232629; color: #cfcfc2;"><b>def</b> activation_function (<span style="color: #27aeae;">self</span>, x) :
<span style="color: #7a7c7d;">"""Logistic function</span>
<span style="color: #7a7c7d;"> """</span>
e = <span style="color: #f67400;">2.718281828459045</span>
<b><span style="color: #fdbc4b;">return</span></b> (<span style="color: #f67400;">1.0</span> / (<span style="color: #f67400;">1.0</span> + (e ** (-<span style="color: #f67400;">1.0</span> * x))))</pre>
<p>Полагаю, показывать полный код каждой сети смысла нет. Различие с кодом из прошлой статьи исключительно в функции активации. Из сказанного следует, что новая функция будет использоваться не во всех нейронах. Никаких изменений во входных нейронах не будет.</p>
<p>Первая нейронная сеть</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-ko5U90qanS-v7Qdnt6lA1fGwTcGPlALCllzWddv3dyHCrcl6KxBgJcWwQyEpHrL4LJFmMnu6d8yvG_kbsq22ZWCKIuoBobBXcJERFvepzWlPpKoLr5z3soQa4FvT8tRQhQDv4ir0MoPW/s850/and_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="850" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-ko5U90qanS-v7Qdnt6lA1fGwTcGPlALCllzWddv3dyHCrcl6KxBgJcWwQyEpHrL4LJFmMnu6d8yvG_kbsq22ZWCKIuoBobBXcJERFvepzWlPpKoLr5z3soQa4FvT8tRQhQDv4ir0MoPW/w400-h376/and_3.png" width="400" /></a></div>
<p>w0 = 1.3<br />w1 = 1.2<br /><br />
Результат выполнения кода<br /><br />
$ python3 ./and_3_logistic.py<br />
0.1 0.1 0.5621765008857981<br />
0.1 0.9 0.7702989490466019<br />
0.9 0.1 0.7841471891774855<br />
0.9 0.9 0.9046505351008904<br /><br />
Едва ли не лучший результат этой сети. И этот результат так себе. Впрочем, это не провал. Если считать ответ сети меньше 0.8 за 0, а ответ больше 0.8 за 1, то сеть работает правильно.</p>
<p>Вторая нейронная сеть</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYwqn-uRdVAO9xlA_jpTayUytqgZJ2L_8G-FxGCKM591XSC15N6ovUMJehWmzDiSBSSxPeir1foXZ3Kg3XTeqgBqKXeRFHuwy3aPc-rExk1vwpTsFeo-R8h86FJNIRhU8HOvPMTY6clTgY/s1200/and_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYwqn-uRdVAO9xlA_jpTayUytqgZJ2L_8G-FxGCKM591XSC15N6ovUMJehWmzDiSBSSxPeir1foXZ3Kg3XTeqgBqKXeRFHuwy3aPc-rExk1vwpTsFeo-R8h86FJNIRhU8HOvPMTY6clTgY/w400-h266/and_5.png" width="400" /></a></div>
<p>w0 = 0.6<br />
w1 = -1.1<br />
w2 = 13.9<br />
w3 = -2.2<br />
w4 = -20.6<br />
w5 = 10.3<br /><br />
Результат выполнения кода<br /><br />
$ python3 ./and_5_logistic.py<br />
0.1 0.1 0.10136400812341441<br />
0.1 0.9 0.10387328161724185<br />
0.9 0.1 0.10146562216498858<br />
0.9 0.9 0.9071138135502281<br /><br />
Результат близок и идеалу. Ответы, получаемые от этой сети, существенно отличаются от ответов предыдущей сети. При использовании линейной функции активации такого не наблюдалось.</p>
<p>Третья нейронная сеть</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPGpIu4HS1toy0Q9qhRsGXA87D7wUYXNI2nmZqFPks_MvYbQ2e5RLhPCJ5cq4zdW7wSxDU1Ds0g70iWTi6T0fINZwvb4NtegPAMtdA530uhd-3m6-UV8samLRtwDtIXLkCLMhdZpZscqDS/s1200/and_6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPGpIu4HS1toy0Q9qhRsGXA87D7wUYXNI2nmZqFPks_MvYbQ2e5RLhPCJ5cq4zdW7wSxDU1Ds0g70iWTi6T0fINZwvb4NtegPAMtdA530uhd-3m6-UV8samLRtwDtIXLkCLMhdZpZscqDS/w400-h266/and_6.png" width="400" /></a></div>
<p>w0 = -14.4<br />
w1 = 0.8<br />
w2 = 6.8<br />
w3 = -4.2<br />
w4 = 3.4<br />
w5 = -5.0<br />
w6 = -6.8<br />
w7 = 3.8<br />
w8 = -6.4<br /><br />
Результат выполнения кода<br /><br />
$ python3 ./and_6_logistic.py<br />
[0.1, 0.1] [0.10085496232204445]<br />
[0.1, 0.9] [0.10332463740837802]<br />
[0.9, 0.1] [0.10401008170139892]<br />
[0.9, 0.9] [0.9038013292059486]<br /><br />
Результат практически не отличается от показанного второй сетью. Более сложная сеть может всё, что может менее сложная сеть. Очевидный вывод.<br /><br />
Подводя общий итог следует сказать, что нелинейность логистической функции позволяет нейронной сети работать совершенно иначе. Нейроны скрытого слоя сильно влияют на возможности сети. Даже на таком простом примере стало возможным получение намного лучшего результата.</p>Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-76198334734833175712020-11-29T12:33:00.002-08:002020-11-29T17:39:25.656-08:00Нейронная сеть. Часть 1.<p>Приступая к изучению нового следует начинать с самого простого. Вот я и решил сделать на нейронной сети побитовое И.</p><a name='more'></a><p>Вообще то, побитовое И представляет собой операцию между двумя отдельными битами. Бит может быть 0 или 1. Таким образом, получается всего четыре варианта.<br /><br />0 & 0 = 0<br />0 & 1 = 0<br />1 & 0 = 0<br />1 & 1 = 1<br /><br />Но на вход нейронной сети не обязательно подавать 0 и 1. За 0 и 1 можно считать что угодно. Получение 0 и 1 на выходе также не обязательно. Необходима лишь возможность однозначной интерпретации результата работы нейронной сети.<br /><br />Сама нейронная сеть состоит из нейронов. Неожиданно? Да? У нейронов может быть несколько входов и один выход. С каждым отдельным входом связан определенный весовой коэффициент (вес связи). Данные с входов умножаются на соответствующие им веса и все полученные значения складываются. Затем результат передается в функцию активации, а возвращенное функцией активации значение является выходными данными нейрона. Как не трудно догадаться, нейроны в сети соединены друг с другом определенным образом (данные с выхода одних нейронов поступают на вход других).<br /><br />В нейронных сетях показанных ниже будет использоваться линейная функция активации.<br /></p><p> </p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi01lUDcV60viq5Dz5CJvCq3CIB8gwrZFlp8wRL2fvyhtK7dCuFlVlsqUgVjvj6WEHkMe1bDcvTnhstNNDgznT1PCD8RSTBkwAVEfKIjruuTeTD44Iln2_clt3mX4EllDTSjhOVqpu4xbZy/s803/identity_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="803" data-original-width="803" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi01lUDcV60viq5Dz5CJvCq3CIB8gwrZFlp8wRL2fvyhtK7dCuFlVlsqUgVjvj6WEHkMe1bDcvTnhstNNDgznT1PCD8RSTBkwAVEfKIjruuTeTD44Iln2_clt3mX4EllDTSjhOVqpu4xbZy/w400-h400/identity_1.png" width="400" /></a></div>
<br /><p></p><p>y = x<br /><br />Простой и очень быстрый вариант.<br /><br />Самая первая нейронная сеть будет состоять из трех нейронов. Два входных нейрона и один выходной.</p><br /><p></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeZ95SMCMWDVugbuLPefYUJGUnXxBaafcUE_8x_lcyMa59nEyRVx3uXpg1N80DbfDz6cXxLtetMN1Ipdb2XKimo12A7RA4RE1aWu2pRBfyeusWOgPTjWreajEBZ10NKrBDAYVx2kI_90XM/s850/and_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="850" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeZ95SMCMWDVugbuLPefYUJGUnXxBaafcUE_8x_lcyMa59nEyRVx3uXpg1N80DbfDz6cXxLtetMN1Ipdb2XKimo12A7RA4RE1aWu2pRBfyeusWOgPTjWreajEBZ10NKrBDAYVx2kI_90XM/w400-h376/and_3.png" width="400" /></a></div>
<p><br />Отдельный входной нейрон можно представить, как нейрон с одним входом, весовой коэффициент которого равен 1 и линейной функцией активации. Данные на выходе такого нейрона такие же как и на входе. Поэтому какие либо вычисления для входных нейронов не требуются.<br /><br />w0, w1 - веса связей выходного нейрона. От значения этих переменных зависит результат выдаваемый нейронной сетью. Первая сеть очень простая. Подходящие веса можно легко вычислить.<br /><br />Код</p>
<pre style="background-color: #232629; color: #cfcfc2;"><span style="color: #7a7c7d;">#!/usr/bin/env python3</span>
<span style="color: #7a7c7d;"># coding: utf-8</span>
<span style="color: #7a7c7d;"># Neural network.</span>
<span style="color: #7a7c7d;"># First layer: 2 input neurons.</span>
<span style="color: #7a7c7d;"># Second layer: 1 output neuron.</span>
<span style="color: #7a7c7d;"># Identity activation function.</span>
<b>class</b> neural_network :
<b>def</b> <span style="color: #8e44ad;">__init__</span> (<span style="color: #27aeae;">self</span>) :
<span style="color: #27aeae;">self</span>.w0 = <span style="color: #f67400;">0.4</span>
<span style="color: #27aeae;">self</span>.w1 = <span style="color: #f67400;">0.4</span>
<b>def</b> activation_function (<span style="color: #27aeae;">self</span>, x) :
<span style="color: #7a7c7d;">"""Identity function</span>
<span style="color: #7a7c7d;"> """</span>
<b><span style="color: #fdbc4b;">return</span></b> (x)
<b>def</b> query (<span style="color: #27aeae;">self</span>, input0, input1) :
output = (input0 * <span style="color: #27aeae;">self</span>.w0) + (input1 * <span style="color: #27aeae;">self</span>.w1)
output = <span style="color: #27aeae;">self</span>.activation_function(output)
<b><span style="color: #fdbc4b;">return</span></b> (output)
nn = neural_network ()
a = <span style="color: #f67400;">0.1</span>
b = <span style="color: #f67400;">0.9</span>
<span style="color: #7f8c8d;">print</span> (a, a, nn.query(a, a))
<span style="color: #7f8c8d;">print</span> (a, b, nn.query(a, b))
<span style="color: #7f8c8d;">print</span> (b, a, nn.query(b, a))
<span style="color: #7f8c8d;">print</span> (b, b, nn.query(b, b))
<span style="color: #7a7c7d;"># End</span>
</pre>
<p>Результат выполнения кода<br /></p><p>$ python3 ./and_3_identity.py<br />0.1 0.1 0.08<br />0.1 0.9 0.40<br />0.9 0.1 0.40<br />0.9 0.9 0.72<br /><br /></p><p>Результат вполне приемлем. Если округлить результат до ближайшего целого, получается сносно.<br /><br />Вторая нейронная сеть состоит из двух входных нейронов, двух нейронов скрытого слоя и одного выходного нейрона.</p><p><br /></p><p></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeWWFWlppCd1XGobwUhoD2fbDk4HHJq-DSrwEKmQKdHOT_iTfJ6EK06vWxJDs8INMApSRqaKDfFl94Mt-36vFpCfvBfF5Pvi5u31v89KHXrppPnzvA9ST9IV-Fsdj724VNieFgl_BLpEne/s1200/and_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeWWFWlppCd1XGobwUhoD2fbDk4HHJq-DSrwEKmQKdHOT_iTfJ6EK06vWxJDs8INMApSRqaKDfFl94Mt-36vFpCfvBfF5Pvi5u31v89KHXrppPnzvA9ST9IV-Fsdj724VNieFgl_BLpEne/w400-h266/and_5.png" width="400" /></a></div>
<p><br /></p><p>w0, w1 - веса связей первого нейрона скрытого слоя. w2, w3 - веса связей второго нейрона скрытого слоя. w4, w5 - веса связей выходного нейрона.</p><p>Код</p>
<pre style="background-color: #232629; color: #cfcfc2;"><span style="color: #7a7c7d;">#!/usr/bin/env python3</span>
<span style="color: #7a7c7d;"># coding: utf-8</span>
<span style="color: #7a7c7d;"># Neural network.</span>
<span style="color: #7a7c7d;"># First layer: 2 input neurons.</span>
<span style="color: #7a7c7d;"># Second layer: 2 hidden neurons.</span>
<span style="color: #7a7c7d;"># Third layer: 1 output neuron.</span>
<span style="color: #7a7c7d;"># Identity activation function.</span>
<b>class</b> neural_network :
<b>def</b> <span style="color: #8e44ad;">__init__</span> (<span style="color: #27aeae;">self</span>) :
<span style="color: #27aeae;">self</span>.w0 = -<span style="color: #f67400;">4.2</span>
<span style="color: #27aeae;">self</span>.w1 = -<span style="color: #f67400;">3.8</span>
<span style="color: #27aeae;">self</span>.w2 = <span style="color: #f67400;">1.7</span>
<span style="color: #27aeae;">self</span>.w3 = <span style="color: #f67400;">1.5</span>
<span style="color: #27aeae;">self</span>.w4 = -<span style="color: #f67400;">0.3</span>
<span style="color: #27aeae;">self</span>.w5 = -<span style="color: #f67400;">0.5</span>
<b>def</b> activation_function (<span style="color: #27aeae;">self</span>, x) :
<span style="color: #7a7c7d;">"""Identity function</span>
<span style="color: #7a7c7d;"> """</span>
<b><span style="color: #fdbc4b;">return</span></b> (x)
<b>def</b> query (<span style="color: #27aeae;">self</span>, input0, input1) :
hidden0 = (input0 * <span style="color: #27aeae;">self</span>.w0) + (input1 * <span style="color: #27aeae;">self</span>.w1)
hidden0 = <span style="color: #27aeae;">self</span>.activation_function(hidden0)
hidden1 = (input0 * <span style="color: #27aeae;">self</span>.w2) + (input1 * <span style="color: #27aeae;">self</span>.w3)
hidden1 = <span style="color: #27aeae;">self</span>.activation_function(hidden1)
output = (hidden0 * <span style="color: #27aeae;">self</span>.w4) + (hidden1 * <span style="color: #27aeae;">self</span>.w5)
output = <span style="color: #27aeae;">self</span>.activation_function(output)
<b><span style="color: #fdbc4b;">return</span></b> (output)
nn = neural_network ()
a = <span style="color: #f67400;">0.1</span>
b = <span style="color: #f67400;">0.9</span>
<span style="color: #7f8c8d;">print</span> (a, a, nn.query(a, a))
<span style="color: #7f8c8d;">print</span> (a, b, nn.query(a, b))
<span style="color: #7f8c8d;">print</span> (b, a, nn.query(b, a))
<span style="color: #7f8c8d;">print</span> (b, b, nn.query(b, b))
<span style="color: #7a7c7d;"># End</span>
</pre>
<p>Результат выполнения кода<br /></p><p>$ python3 ./and_5_identity.py<br />0.1 0.1 0.07999<br />0.1 0.9 0.39199<br />0.9 0.1 0.40799<br />0.9 0.9 0.72000<br /></p><p>Результат не сильно отличается от полученного ранее.<br /><br />Третья нейронная сеть состоит из двух входных нейронов, трех нейронов скрытого слоя и одного выходного нейрона.<br /></p><p><br /></p><p></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOTHmGCNCvq1tUKiWDTmy3g6hm-F-gzw1Hof8Ohj98J7Pz9tpC6Ovq0X4Mihc1Sb3UvPpXFzX3qq777DXK7VI8yqzAsDMtE6K_44PyAIjXT-q_WAaiEg-9C2yGGUVRNEzjUlyLEuJSglGL/s1200/and_6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1200" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOTHmGCNCvq1tUKiWDTmy3g6hm-F-gzw1Hof8Ohj98J7Pz9tpC6Ovq0X4Mihc1Sb3UvPpXFzX3qq777DXK7VI8yqzAsDMtE6K_44PyAIjXT-q_WAaiEg-9C2yGGUVRNEzjUlyLEuJSglGL/w400-h266/and_6.png" width="400" /></a></div>
<p><br /></p><p>Сразу приведу один из возможных вариантов значений весов для этой нейронной сети.<br /><br />w0 = 5.0<br />w1 = -2.4<br />w2 = 1.2<br />w3 = -0.8<br />w4 = -1.4<br />w5 = 1.0<br />w6 = 0.8<br />w7 = -4.4<br />w8 = -1.2<br /><br />Код</p>
<pre style="background-color: #232629; color: #cfcfc2;"><span style="color: #7a7c7d;">#!/usr/bin/env python3</span>
<span style="color: #7a7c7d;"># coding: utf-8</span>
<span style="color: #7a7c7d;"># Neural network.</span>
<span style="color: #7a7c7d;"># First layer: 2 input neurons.</span>
<span style="color: #7a7c7d;"># Second layer: 3 hidden neurons.</span>
<span style="color: #7a7c7d;"># Third layer: 1 output neuron.</span>
<span style="color: #7a7c7d;"># Identity activation function.</span>
<b>class</b> neural_network :
<b>def</b> <span style="color: #8e44ad;">__init__</span> (<span style="color: #27aeae;">self</span>) :
<span style="color: #27aeae;">self</span>.hidden_weight = [[<span style="color: #f67400;">5.0</span>, -<span style="color: #f67400;">2.4</span>], [<span style="color: #f67400;">1.2</span>, -<span style="color: #f67400;">0.8</span>], [-<span style="color: #f67400;">1.4</span>, <span style="color: #f67400;">1.0</span>]]
<span style="color: #27aeae;">self</span>.output_weight = [[<span style="color: #f67400;">0.8</span>, -<span style="color: #f67400;">4.4</span>, -<span style="color: #f67400;">1.2</span>]]
<b>def</b> activation_function (<span style="color: #27aeae;">self</span>, x) :
<span style="color: #7a7c7d;">"""Identity function</span>
<span style="color: #7a7c7d;"> """</span>
<b><span style="color: #fdbc4b;">return</span></b> (x)
<b>def</b> query (<span style="color: #27aeae;">self</span>, input_data) :
hidden_data = [<span style="color: #f67400;">0</span>, <span style="color: #f67400;">0</span>, <span style="color: #f67400;">0</span>]
output_data = [<span style="color: #f67400;">0</span>]
hidden_data[<span style="color: #f67400;">0</span>] += input_data[<span style="color: #f67400;">0</span>] * <span style="color: #27aeae;">self</span>.hidden_weight[<span style="color: #f67400;">0</span>][<span style="color: #f67400;">0</span>]
hidden_data[<span style="color: #f67400;">0</span>] += input_data[<span style="color: #f67400;">1</span>] * <span style="color: #27aeae;">self</span>.hidden_weight[<span style="color: #f67400;">0</span>][<span style="color: #f67400;">1</span>]
hidden_data[<span style="color: #f67400;">0</span>] = <span style="color: #27aeae;">self</span>.activation_function(hidden_data[<span style="color: #f67400;">0</span>])
hidden_data[<span style="color: #f67400;">1</span>] += input_data[<span style="color: #f67400;">0</span>] * <span style="color: #27aeae;">self</span>.hidden_weight[<span style="color: #f67400;">1</span>][<span style="color: #f67400;">0</span>]
hidden_data[<span style="color: #f67400;">1</span>] += input_data[<span style="color: #f67400;">1</span>] * <span style="color: #27aeae;">self</span>.hidden_weight[<span style="color: #f67400;">1</span>][<span style="color: #f67400;">1</span>]
hidden_data[<span style="color: #f67400;">1</span>] = <span style="color: #27aeae;">self</span>.activation_function(hidden_data[<span style="color: #f67400;">1</span>])
hidden_data[<span style="color: #f67400;">2</span>] += input_data[<span style="color: #f67400;">0</span>] * <span style="color: #27aeae;">self</span>.hidden_weight[<span style="color: #f67400;">2</span>][<span style="color: #f67400;">0</span>]
hidden_data[<span style="color: #f67400;">2</span>] += input_data[<span style="color: #f67400;">1</span>] * <span style="color: #27aeae;">self</span>.hidden_weight[<span style="color: #f67400;">2</span>][<span style="color: #f67400;">1</span>]
hidden_data[<span style="color: #f67400;">2</span>] = <span style="color: #27aeae;">self</span>.activation_function(hidden_data[<span style="color: #f67400;">2</span>])
output_data[<span style="color: #f67400;">0</span>] += hidden_data[<span style="color: #f67400;">0</span>] * <span style="color: #27aeae;">self</span>.output_weight[<span style="color: #f67400;">0</span>][<span style="color: #f67400;">0</span>]
output_data[<span style="color: #f67400;">0</span>] += hidden_data[<span style="color: #f67400;">1</span>] * <span style="color: #27aeae;">self</span>.output_weight[<span style="color: #f67400;">0</span>][<span style="color: #f67400;">1</span>]
output_data[<span style="color: #f67400;">0</span>] += hidden_data[<span style="color: #f67400;">2</span>] * <span style="color: #27aeae;">self</span>.output_weight[<span style="color: #f67400;">0</span>][<span style="color: #f67400;">2</span>]
output_data[<span style="color: #f67400;">0</span>] = <span style="color: #27aeae;">self</span>.activation_function(output_data[<span style="color: #f67400;">0</span>])
<b><span style="color: #fdbc4b;">return</span></b> (output_data)
nn = neural_network ()
a = <span style="color: #f67400;">0.1</span>
b = <span style="color: #f67400;">0.9</span>
<span style="color: #7f8c8d;">print</span> ([a, a], nn.query([a, a]))
<span style="color: #7f8c8d;">print</span> ([a, b], nn.query([a, b]))
<span style="color: #7f8c8d;">print</span> ([b, a], nn.query([b, a]))
<span style="color: #7f8c8d;">print</span> ([b, b], nn.query([b, b]))
<span style="color: #7a7c7d;"># End</span>
</pre>
<p></p><p>Веса записаны как списки. При таком использовании списки python очень похожи на массивы C. Используя этот код уже можно сделать более универсальную реализацию нейронной сети. А ранее представленный код должен был быть более наглядным и продемонстрировать насколько просто сделать нейронную сеть.<br /><br />Результат выполнения кода<br /></p><p>$ python3 ./and_6_identity.py<br />[0.1, 0.1] [0.08000000000000006]<br />[0.1, 0.9] [0.40000000000000036]<br />[0.9, 0.1] [0.39999999999999947]<br />[0.9, 0.9] [0.7199999999999998]<br /></p><p>Результат работы третьей сети очень похож на результаты первой и второй сети. Так и должно быть :)<br /><br />Можно подвести некоторые итоги. Использование скрытого слоя в нейронной сети, где применяется только линейная функция активации не кажется хорошей идеей. Однако, сеть с большим количеством нейронов позволяет получить аналогичный результат при большем числе вариантов значений весовых коэффициентов. Будет ли это полезно? Пока не знаю.<br /></p>Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-49356042897303597312017-12-04T12:47:00.002-08:002017-12-04T12:47:49.427-08:00Умная розетка<div dir="ltr" style="text-align: left;" trbidi="on">
Сделал устройство включающее и выключающее 220 вольт переменного тока. Управление устройством осуществляется с компьютера через bluetooth.<br />
<br />
<a name='more'></a><br />
Ток в розетке смертельно опасен!!! Без знания и соблюдения техники безопасности в розетку лезть не надо!<br />
<br />
Сейчас можно купить готовое устройство. Например, <a href="http://s.click.aliexpress.com/e/vFeM3rZ" target="_blank">Broadlink</a>.<br />
<br />
Есть решения дешевле. Например, <a href="http://s.click.aliexpress.com/e/RNzfM33" target="_blank">Sonoff</a>. Но здесь уже необходимы знания и опыт работы с переменным током 220 вольт.<br />
<br />
Чем самодельное устройство лучше? Его можно сделать на любой ток, любую мощность. И оно будет работать именно так как нужно. Алгоритм, в любой момент, можно подкорректировать.<br />
<br />
У меня включение и выключение 220 вольт осуществляется твердотельным реле<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJGFlL99mRQzpg1UTAI6lfwfaeNRVEaHyQYweP8icc5mWT6wzA4Qjcoi40A0pfRhtj2a49tN9aPZBY8n7F36mtvmBQAedt9LU2qjrtouFmnAobO-tfdAPJ6gSMuOZ7oh1aDvwqq44JkYV-/s1600/SSR-40DA.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJGFlL99mRQzpg1UTAI6lfwfaeNRVEaHyQYweP8icc5mWT6wzA4Qjcoi40A0pfRhtj2a49tN9aPZBY8n7F36mtvmBQAedt9LU2qjrtouFmnAobO-tfdAPJ6gSMuOZ7oh1aDvwqq44JkYV-/s400/SSR-40DA.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/qbA2RzR" target="_blank">SSR-40 DA</a><br />
<br />
Для этих реле есть специальные радиаторы<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJP-WcDwrmNZZzD8voN-mC0ML6kO2LTaW9JGpJx37tYVzQRH9WKvAg0CqiiUFK2Ml5jDXeUcy8G8Q3dMlq7P_PNyfFDsuB7asIa3E7fV7BsHNrmAp2-U08QU9vXbI4Lc4mLI1b7kJIt6j1/s1600/radiator_01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJP-WcDwrmNZZzD8voN-mC0ML6kO2LTaW9JGpJx37tYVzQRH9WKvAg0CqiiUFK2Ml5jDXeUcy8G8Q3dMlq7P_PNyfFDsuB7asIa3E7fV7BsHNrmAp2-U08QU9vXbI4Lc4mLI1b7kJIt6j1/s400/radiator_01.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/Q7MFmy7" target="_blank">Radiator SSR 10A-40A</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDX-zQDaTqefNxYFIpJwr7ruLxVsNbKJziAQbpBuYCewXigaaar8_qbqA4fe_CkiG2YrO9yL76KTvGeKYAxAyUYNv0G8R3-oeW2A0glYupZ1zsVAsN1eG8koYQ9fuq2WmYGkFQubZYiqGw/s1600/radiator_02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDX-zQDaTqefNxYFIpJwr7ruLxVsNbKJziAQbpBuYCewXigaaar8_qbqA4fe_CkiG2YrO9yL76KTvGeKYAxAyUYNv0G8R3-oeW2A0glYupZ1zsVAsN1eG8koYQ9fuq2WmYGkFQubZYiqGw/s400/radiator_02.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/IEiurzb" target="_blank">Radiator SSR 10A-100A</a><br />
<br />
Без радиаторов твердотельные реле сильно греются, даже при токе в несколько ампер.<br />
<br />
Реле управляется ардуино нано<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtll_uvKyy_p0MKEOs3ZCpYpPbSQnwY19NHLUQPwVCJ-sa-bH4IAafCdOCo_G0xqs1CMLY2xg9N2utx7FIPiprEMh4ak_Y6O2ZBL7s2eYmZaE1OQh01K9fLuDXU8gyhgByCnQ6rhOFHSid/s1600/arduino_nano-3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtll_uvKyy_p0MKEOs3ZCpYpPbSQnwY19NHLUQPwVCJ-sa-bH4IAafCdOCo_G0xqs1CMLY2xg9N2utx7FIPiprEMh4ak_Y6O2ZBL7s2eYmZaE1OQh01K9fLuDXU8gyhgByCnQ6rhOFHSid/s400/arduino_nano-3.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/fQ7MR7m" target="_blank">Ардуино Нано</a><br />
<br />
Для ардуино нано есть удобный сенсор шильд<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXh6mcUjfZCFlyWeSUC9PPTJiZEdCXBssKXYRJ2HPnEohIdOu2eObA6rnJzvT5Dn4g8Pp72x2AYHdjTbN_Igz4nSoPZh6rGIlmqteVCn4aYoxjEkKVGSu2mu_xrTorSOB1a-njX0xrwFU5/s1600/sensor_shield-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1536" data-original-width="1600" height="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXh6mcUjfZCFlyWeSUC9PPTJiZEdCXBssKXYRJ2HPnEohIdOu2eObA6rnJzvT5Dn4g8Pp72x2AYHdjTbN_Igz4nSoPZh6rGIlmqteVCn4aYoxjEkKVGSu2mu_xrTorSOB1a-njX0xrwFU5/s400/sensor_shield-2.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/RzbAUnE" target="_blank">Сенсор шилд</a><br />
<br />
И bluetooth модуль<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhryihC53VwgXiDiEelEtiGWN19LoTNiIyiiauMCppWshCkoxYkkc1FssCWho95aQzuY7A4To0Y-n6W03oCZeAtmCnuTB1BloJCGUvsm1RjdOV-bigEmhgOl3KmtMQlaoYAlhsF4c7SgbbL/s1600/bluetooth.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhryihC53VwgXiDiEelEtiGWN19LoTNiIyiiauMCppWshCkoxYkkc1FssCWho95aQzuY7A4To0Y-n6W03oCZeAtmCnuTB1BloJCGUvsm1RjdOV-bigEmhgOl3KmtMQlaoYAlhsF4c7SgbbL/s400/bluetooth.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/MZVBMfu" target="_blank">Bluetooth Module</a><br />
<br />
Соединяется всё согласно приведенным ниже инструкциям.<br />
<br />
Выводы 1 и 2 твердотельного реле включаются в разрыв цепи переменного тока 220 вольт. Проще говоря, один из проводов идущий к нагрузке разрезается и получившиеся выводы подключаются к разъемам 1 и 2 твердотельного реле.<br />
<br />
Arduino Nano --- SSR<br />
GND --- 4<br />
D13 --- 3<br />
<br />
Arduino Nano --- Bluetooth Module<br />
VCC --- VCC<br />
GND --- GND<br />
D0 --- TXD<br />
D1 --- RXD<br />
<br />
Bluetooth модуль подключается к ардуино после загрузки программы в контроллер. Иначе программу загрузить не получится.<br />
<br />
Для питания ардуино нано от сети 220 вольт переменного тока нужна специальная платка<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyCWXcQ1STPP_ZOO6I5ZvQFMJqQugcvC3JhwdsnhQ3rpvzU_9m_FYb6D_HalgIV4qifP69tIFIOFrTtUMCH3aTJTFWV-hs1CJ0XABryDHuiIWd0VwrqkNkEKQVBzI-QGjfOXEUahqPJDC5/s1600/ac-dc.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="839" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyCWXcQ1STPP_ZOO6I5ZvQFMJqQugcvC3JhwdsnhQ3rpvzU_9m_FYb6D_HalgIV4qifP69tIFIOFrTtUMCH3aTJTFWV-hs1CJ0XABryDHuiIWd0VwrqkNkEKQVBzI-QGjfOXEUahqPJDC5/s400/ac-dc.jpg" width="381" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/fYbYvvr" target="_blank">AC-DC Power Step Down Module</a><br />
<br />
Или можно взять обычную пятивольтовую зарядку<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhACm4vQGO6_aOwE7KB_e_lTf7lhIrcf9EH8VcMbo_8obrJ6sdsxRaNKhRDHhIyXoB4-E_cclV2Ux3xZzfV6JZuHDmSI5z5e-J_TELkc5b4FmjtdZbrgHUKqs83Zqg6SHCb0GAbTBuQRLeW/s1600/Choetech-5V.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhACm4vQGO6_aOwE7KB_e_lTf7lhIrcf9EH8VcMbo_8obrJ6sdsxRaNKhRDHhIyXoB4-E_cclV2Ux3xZzfV6JZuHDmSI5z5e-J_TELkc5b4FmjtdZbrgHUKqs83Zqg6SHCb0GAbTBuQRLeW/s400/Choetech-5V.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/ZFeiU7I" target="_blank">Charger</a><br />
<br />
Программа для ардуино нано (C/C++)<br />
<br />
<pre>////////////////////////
//
// Arduino
//
////////////////////////
//
// Sketch:
//
#define RELAY_PORT PORTB
#define RELAY_DDR DDRB
#define RELAY 5
volatile unsigned char data = 0;
volatile unsigned char flag = 0;
volatile unsigned char on = 0;
volatile unsigned char off = 0;
volatile unsigned char sec = 0;
volatile unsigned char min = 0;
volatile unsigned char stage = 0;
void PORT_Init( void )
{
// Port B
DDRB = 0b00000000;
PORTB = 0b00000000;
// Port C
DDRC = 0b00000000;
PORTC = 0b00000000;
// Port D
DDRD = 0b00000000;
PORTD = 0b00000000;
}
void Relay_Init( void )
{
RELAY_DDR |= (1<<RELAY);
RELAY_PORT &= ~(1<<RELAY);
}
void Timer0_Init( void )
{
// TC0 Counter Value Register
TCNT0 = 0;
// TC0 Control Register A
// Bits: COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00
TCCR0A = 0;
// TC0 Control Register B
// Bits: FOC0A FOC0B - - WGM02 CS02 CS01 CS00
TCCR0B = 0; // No clock source (stopped)
// TC0 Interrupt Mask Register
// Bits: - - - - - OCIE0B OCIE0A TOIE0
TIMSK0 = 0;
// TC0 Interrupt Flag Register
// Bits: - - - - - OCF0B OCF0A TOV0
TIFR0 = 0;
}
void Timer1_Init( void )
{
// TC1 Counter Value Register
TCNT1 = 3035;
// TC1 Control Register A
// Bits: COM1A1 COM1A0 COM1B1 COM1B0 - - WGM11 WGM10
TCCR1A = 0;
// TC1 Control Register B
// Bits: ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
TCCR1B = (1<<CS12); // CLK / 256
// TC1 Control Register C
// Bits: FOC1A FOC1B - - - - - -
TCCR1C = 0;
// TC1 Interrupt Mask Register
// Bits: - - ICIE1 - - OCIE1B OCIE1A TOIE1
TIMSK1 = (1<<TOIE1);
// TC1 Interrupt Flag Register
// Bits: – – ICF1 – - OCF1B OCF1A TOV1
TIFR1 = (1<<TOV1);
}
void Timer2_Init( void )
{
// TC2 Counter Value Register
TCNT2 = 0;
// TC2 Control Register A
// COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
TCCR2A = 0;
// TC2 Control Register B
// FOC2A FOC2B - - WGM22 CS22 CS21 CS20
TCCR2B = 0; // No clock source (stopped)
// TC2 Interrupt Mask Register
// - - - - - OCIE2B OCIE2A TOIE2
TIMSK2 = 0;
// TC2 Interrupt Flag Register
// - - - - - OCF2B OCF2A TOV2
TIFR2 = 0;
}
void USART_Init( void )
{
// Set baud rate (9600 bps)
UBRR0H = 0x00;
UBRR0L = 0x67;
// Enable receiver and transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Set frame format: 8 data, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}
unsigned char USART_Receive( void )
{
// Wait for data to be received
while ( !(UCSR0A & (1<<RXC0)) ) ;
// Get and return received data from buffer
return UDR0;
}
void USART_Transmit( unsigned char data )
{
// Wait for empty transmit buffer
while ( !( UCSR0A & (1<<UDRE0)) ) ;
// Put data into buffer, sends the data
UDR0 = data;
}
void setup()
{
cli();
PORT_Init();
Relay_Init();
Timer0_Init();
Timer1_Init();
Timer2_Init();
USART_Init();
sei();
}
void loop()
{
while (1)
{
data = USART_Receive();
if ( data == 255 )
{
USART_Transmit( stage );
}
else if ( data == 254 )
{
USART_Transmit( on );
}
else if ( data == 253 )
{
USART_Transmit( off );
}
else if ( data == 252 )
{
flag = 1;
}
else if ( data == 251 )
{
flag = 0;
}
else if ( flag == 1 )
{
on = data;
}
else
{
off = data;
}
}
}
ISR(TIMER1_OVF_vect)
{
TCNT1 = 3035;
sec += 1;
if ( sec == 60 )
{
min += 1;
sec = 0;
}
if ( min == 240 )
{
min = 0;
}
if ( stage == 0 )
{
if ( on != 0 )
{
RELAY_PORT |= (1<<RELAY);
// USART_Transmit( '1' ); // test
}
sec = 0;
min = 0;
stage = 1;
}
if ( stage == 1 && min >= on )
{
stage = 2;
}
if ( stage == 2 )
{
if ( off != 0 )
{
RELAY_PORT &= ~(1<<RELAY);
// USART_Transmit( '0' ); // test
}
sec = 0;
min = 0;
stage = 3;
}
if ( stage == 3 && min >= off )
{
stage = 0;
}
}
//
// End
//
////////////////////////</pre>
<br />
Программа для компьютера (python)<br />
<br />
<pre>#!/usr/bin/env python
# coding: utf-8
import serial
port_number = 2 # COM3
baud_rate = 9600 # bps
# open port
ser = serial.Serial(port_number,
baud_rate,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
timeout = 1)
print ser, '\n' # print port information
# communication
while 1 :
tmp = raw_input('quit: ')
if tmp :
break
while 1 :
on = raw_input('on (0 ... 240): ')
if not on :
break
try :
tmp = int(on)
except ValueError :
continue
if tmp < 0 :
continue
if tmp > 240 :
continue
ser.write(chr(252))
ser.write(chr(tmp))
break
while 1 :
off = raw_input('off (0 ... 240): ')
if not off :
break
try :
tmp = int(off)
except ValueError :
continue
if tmp < 0 :
continue
if tmp > 240 :
continue
ser.write(chr(251))
ser.write(chr(tmp))
break
while 1 :
tmp = ser.read()
if not tmp :
break
ser.write(chr(255))
tmp = ser.read()
if tmp :
stage = ord(tmp)
else :
stage = ''
print 'error 255'
while 1 :
tmp = ser.read()
if not tmp :
break
ser.write(chr(254))
on = ser.read()
if on :
print 'on:', ord(on),
if stage == 0 or stage == 1 :
print '*'
else :
print ''
else :
print 'error 254'
while 1 :
tmp = ser.read()
if not tmp :
break
ser.write(chr(253))
off = ser.read()
if off :
print 'off:', ord(off),
if stage == 2 or stage == 3 :
print '*'
else :
print ''
else :
print 'error 253'
print ''
# close port
ser.close()
print ''
# C:/Python27/python.exe C:\220\console.py</pre>
<br />
Работа программы<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAnJ5laIol7ZmKtu2Rvv1s0bU1V6uDvyNPS0gF-jdyUmhoLGmIVabyyfuWSEM7lj_u3SNFYQJbDojfMYQzYlFtH20_yqL8zBKzKfoscEsTIIQ6rboPhLFqMQRI9fa-w2l78PA4u5QPMxFE/s1600/screen-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="531" data-original-width="783" height="271" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAnJ5laIol7ZmKtu2Rvv1s0bU1V6uDvyNPS0gF-jdyUmhoLGmIVabyyfuWSEM7lj_u3SNFYQJbDojfMYQzYlFtH20_yqL8zBKzKfoscEsTIIQ6rboPhLFqMQRI9fa-w2l78PA4u5QPMxFE/s400/screen-1.png" width="400" /></a></div>
<br />
Поясню некоторые моменты. Лучше проверять работу устройства и тестировать код подключив устройство к USB порту компьютера кабелем. А потом, когда всё проверено и настроено, можно использовать bluetooth.<br />
<br />
Ардуино после подачи питания ожидает поступления команд по UART. Ток через реле при этом не идет. Подключенная через реле нагрузка выключена. В зависимости от полученных команд, устройство может подать питание на нагрузку или отключить питание на нагрузке. Но создавался девайс для того, чтобы включать и выключать ток через определенные интервалы времени.<br />
<br />
Управлять устройством можно через монитор порта Arduino IDE. Только это совсем не удобно. Поэтому и была написана специальная программа для компьютера.<br />
<br />
После запуска программа пытается открыть порт COM3. Если ничего не получается, то работа программы завершается. Если всё получается, то появляется запрос на завершение работы программы. Нажав [Enter] продолжим работу программы. Появится запрос времени работы нагрузки в минутах. Можно ввести целое число от 0 до 240. Затем нужно нажать [Enter]. И появится запрос времени в течении которого нагрузка будет отключена. Здесь всё аналогично предшествующему пункту.<br />
<br />
Программа передает введенные данные устройству. Полученный от устройства ответ выводится на экран. Звездочка показывает текущее состояние устройства.<br />
<br />
Если на все запросы жмакать только [Enter], то будут показаны ранее введенные параметры и текущее состояние.<br />
<br />
Если на запрос on ввести 0, а на запрос off ввести число от 1 до 240, то устройство отключит питание на нагрузке. Ток через реле идти не будет. Это состояние будет сохранятся до введения новых команд.<br />
<br />
Если на запрос on ввести число от 1 до 240, а на запрос off ввести 0, то устройство включит питание на нагрузке. Ток через реле будет идти. Это состояние также будет сохранятся до введения новых команд.<br />
<br />
Если на запрос on и на запрос off ввести 0, то устройство будет зафиксировано в текущем состоянии. Я пока не решил баг это или фича, поэтому ничего и не делаю с этим.<br />
<br />
Программа консольная, но вполне удобная. В будущем, возможно, сделаю веб-интерфейс.<br />
<br />
Если есть вопросы по коду, то посмотрите статьи <a href="http://justforduino.blogspot.ru/2014/02/blog-post_9.html" target="_blank">1</a> и <a href="http://justforduino.blogspot.ru/2014/03/blog-post.html" target="_blank">2</a>.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-61426742719789776362017-11-21T13:31:00.000-08:002017-11-22T05:00:02.850-08:00Беспроводная связь<div dir="ltr" style="text-align: left;" trbidi="on">
Это продолжение статьи о радиоуправлении. Здесь рассказывается про управление платформой с компьютера.<br />
<br />
<a name='more'></a><br />
Связь робота с компьютером у меня реализована на радиомодулях представленных ранее.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh-9-M1U8CAS_u2vxt3ixejuuurn2LUHYs3N33wtM62bw49qwyQVhG1z_Z_0eGFQrKmyPUT39AjsJ1o2-H2mGb_a0QnGdG5Wm8rQ25tT3pYlrbxrg7rGrV07xCrtt8-ZD_bAKCoekAvjZZ/s1600/radio-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh-9-M1U8CAS_u2vxt3ixejuuurn2LUHYs3N33wtM62bw49qwyQVhG1z_Z_0eGFQrKmyPUT39AjsJ1o2-H2mGb_a0QnGdG5Wm8rQ25tT3pYlrbxrg7rGrV07xCrtt8-ZD_bAKCoekAvjZZ/s400/radio-1.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/RrZB2FE" target="_blank">Радиомодули</a><br />
<br />
Для подключения радиомодуля к компьютеру нужен USB-UART переходник. Например, на CP2102<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio_Q_CL_XQ_IfXdukg1KjKf-zhckvyUbJrY1r_xvUN9KK7jfNdo3kGByS7eDFCryuCF9-YElxIrPxEATV240hQ09tI2o75jPTj7mE49aA_TdIpLyWqVkzsZ3-Y5cyeOeBpDO0E0a1LHo1H/s1600/cp2102_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio_Q_CL_XQ_IfXdukg1KjKf-zhckvyUbJrY1r_xvUN9KK7jfNdo3kGByS7eDFCryuCF9-YElxIrPxEATV240hQ09tI2o75jPTj7mE49aA_TdIpLyWqVkzsZ3-Y5cyeOeBpDO0E0a1LHo1H/s400/cp2102_1.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/Ba6ufyV" target="_blank">USB-UART переходник</a><br />
<br />
Для windows лучше брать драйвера с официального сайта <a href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank">https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers</a><br />
<br />
Соединяется радиомодуль с USB-UART переходником согласно изложенным ниже инструкциям.<br />
<br />
USB to UART Module --- Transceiver Module<br />
+5V --- VDD<br />
GND --- GND<br />
RXD --- TXD<br />
TXD --- RXD<br />
<br />
Со стороны компьютера это всё выглядит обычным COM портом.<br />
<br />
Теперь управлять роботом можно хоть из монитора порта Arduino IDE.<br />
<br />
Но намного интереснее написать свою программу<br />
<br />
<pre>#!/usr/bin/env python
# coding: utf-8
import serial
port_number = 6 # COM7
baud_rate = 9600 # bps
# open port
ser = serial.Serial(port_number,
baud_rate,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
timeout = 1)
print ser, '\n' # print port information
# communication
while 1 :
data = raw_input('> ')
ser.write(data)
# close port
ser.close()
# C:/Python27/python.exe C:\robot\rc.py</pre>
<br />
Управление платформой реализуется через передачу специальных символов.<br />
<br />
f --- движение вперед<br />
b --- движение назад<br />
l --- поворот налево<br />
r --- поворот направо<br />
s --- остановка<br />
<br />
Можно написать сценарий обеспечивающий прохождение определенного маршрута<br />
<br />
<pre>#!/usr/bin/env python
# coding: utf-8
import time
import serial
port_number = 6 # COM7
baud_rate = 9600 # bps
# open port
ser = serial.Serial(port_number,
baud_rate,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
timeout = 1)
print ser, '\n' # print port information
# communication
ser.write('s')
print time.time(), 'stop'
time.sleep(5)
ser.write('f')
print time.time(), 'forward'
time.sleep(3.5)
ser.write('s')
print time.time(), 'stop'
time.sleep(1)
ser.write('b')
print time.time(), 'backward'
time.sleep(3.5)
ser.write('s')
print time.time(), 'stop'
time.sleep(1)
ser.write('l')
print time.time(), 'left'
time.sleep(4.8)
ser.write('s')
print time.time(), 'stop'
time.sleep(1)
ser.write('r')
print time.time(), 'right'
time.sleep(4.8)
ser.write('s')
print time.time(), 'stop'
time.sleep(1)
# close port
ser.close()
raw_input('')
# C:/Python27/python.exe C:\robot\robot.py</pre>
<br />
С данным кодом робот едет 3.5 секунды вперед. Затем робот едет 3.5 секунды назад. Затем робот поворачивает налево 4.8 секунды. И заканчивается всё поворотом робота направо в течении 4.8 секунд.<br />
<br />
Есть ещё один интересный вариант использования этих радиомодулей. Только их нужно штуки три. Один подключается к ардуино робота. Второй подключается к компьютеру через USB-UART переходник. И третий модуль нужен для пульта.<br />
<br />
Платформа управляется с пульта, а на компьютере записываются все команды оператора.<br />
<br />
<pre>#!/usr/bin/env python
# coding: utf-8
import time
import serial
port_number = 6 # COM7
baud_rate = 9600 # bps
# open port
ser = serial.Serial(port_number,
baud_rate,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
timeout = 1)
print ser, '\n' # print port information
# communication
data = ''
while 1 :
temp = ser.read()
if temp and temp != data :
data = temp
print time.time(), data
# close port
ser.close()
# C:/Python27/python.exe C:\robot\logger.py</pre>
<br />
Ещё платформа может управляется программой с компьютера, а на пульте можно реализовать возможность экстренной остановки платформы.<br />
<br />
У меня робот маленький и не очень быстрый, поэтому последнее решение осталось не реализованным. А в более серьёзных конструкциях нечто подобное быть должно.<br />
<br />
В этой статье нет подробных пояснений по работе с UART модулем контроллера и COM портом компьютера, так как я об этом уже рассказывал (<a href="http://justforduino.blogspot.ru/2014/02/blog-post_9.html" target="_blank">здесь</a> и <a href="http://justforduino.blogspot.ru/2014/03/blog-post.html" target="_blank">здесь</a>).</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-68088696522046374662017-11-09T13:45:00.001-08:002017-11-21T13:42:53.050-08:00Радиоуправление<div dir="ltr" style="text-align: left;" trbidi="on">
Я уже рассказывал про радиоуправляемую машинку (<a href="http://justforduino.blogspot.ru/2015/02/blog-post.html" target="_blank">статья</a>). Но там использовался готовый передатчик и приемник для самолетов. В этой статье описывается радиоуправление на основе модулей для ардуино.<br />
<br />
<a name='more'></a><br />
Радиоуправляемой стала моя новая платформа. Про саму платформу лучше почитать в ранее опубликованных статьях (<a href="http://justforduino.blogspot.ru/2017/01/blog-post.html" target="_blank">железо</a>, <a href="http://justforduino.blogspot.ru/2017/02/blog-post.html" target="_blank">электроника</a>).<br />
<br />
Для этого проекта были куплены радиомодули<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs7z3-ZAlwxzqTaugkgBC-zLQMbhs9UaRpxTslw1Cygorvk4EHN49FbC0MlKU3nBs2w0681Jry-k2RZwCzk55qEp5pOQl2mQ_igy3oDtwgCm-5wnZBaq4tUw5s84moHIoP9uWsHgv-9MJr/s1600/radio-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs7z3-ZAlwxzqTaugkgBC-zLQMbhs9UaRpxTslw1Cygorvk4EHN49FbC0MlKU3nBs2w0681Jry-k2RZwCzk55qEp5pOQl2mQ_igy3oDtwgCm-5wnZBaq4tUw5s84moHIoP9uWsHgv-9MJr/s400/radio-1.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/RrZB2FE" target="_blank">Transceiver Module</a><br />
<br />
Нужно две штуки. А лучше три.<br />
<br />
Для пульта нужна arduino nano<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8hyVUs4YC4-x64hHtFHMPbL1V4eVMy7b19zKF_FMuZjfS28nHTbi3NLLuf70c5qQoX-WIi-82MkmlLnE7MbhGPeSmclWSwWM5pVEk930K4bqdT7MNqSr2puB-x5khp-MI41B0_y0EkYhyphenhyphen/s1600/arduino_nano-3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8hyVUs4YC4-x64hHtFHMPbL1V4eVMy7b19zKF_FMuZjfS28nHTbi3NLLuf70c5qQoX-WIi-82MkmlLnE7MbhGPeSmclWSwWM5pVEk930K4bqdT7MNqSr2puB-x5khp-MI41B0_y0EkYhyphenhyphen/s400/arduino_nano-3.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/fQ7MR7m" target="_blank">Arduino Nano</a><br />
<br />
Удобно использовать arduino nano вместе с шильдиком предназначенным для подключения различных сенсоров <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj85aPkpVtAcDKi1pdwRCdXlLAK69qflbUAln9m2DJ-Y7MRPNGqNGkb_n0U0m7Zf4gYmM9oE6K-n1-Wu1ayM_34MERFrtmiJ3H6SRS3LkTiBU9lVJToiYiftwSO5BE0B-jUroThrFnxiem5/s1600/sensor_shield-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1536" data-original-width="1600" height="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj85aPkpVtAcDKi1pdwRCdXlLAK69qflbUAln9m2DJ-Y7MRPNGqNGkb_n0U0m7Zf4gYmM9oE6K-n1-Wu1ayM_34MERFrtmiJ3H6SRS3LkTiBU9lVJToiYiftwSO5BE0B-jUroThrFnxiem5/s400/sensor_shield-2.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/RzbAUnE" target="_blank">Sensor Shield</a><br />
<br />
Ещё для пульта нужен модуль с кнопочками<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3HDSzKhqR5lb4-499boQSo8KW9kw97UexHFA6kSvmJCVZhHQJS0qxmoHisMEcymVSMOuuoqYpqV-NvAZk-wYgQiwmVdQMK7sk5F-_X45IpBuAh-054KhgpIip552M13yxHz5He3BxeFcw/s1600/key-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3HDSzKhqR5lb4-499boQSo8KW9kw97UexHFA6kSvmJCVZhHQJS0qxmoHisMEcymVSMOuuoqYpqV-NvAZk-wYgQiwmVdQMK7sk5F-_X45IpBuAh-054KhgpIip552M13yxHz5He3BxeFcw/s400/key-2.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/ZRN3F2n" target="_blank">Keyboard Module</a><br />
<br />
Подойдет и такая клавиатурка<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjytxLP5d-13_pBZQ84E2mYYViUkhYuJzuW3IK2B5CwCRXCuG9a-kFLdxRfJF0UNpWkCxPircCw2twrBk0T0FlXoUTqx4wagafgE2yXg3Su5L8vp8mGDJOlJKusuZM4InBbLDG6CVOl0l_q/s1600/key-3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjytxLP5d-13_pBZQ84E2mYYViUkhYuJzuW3IK2B5CwCRXCuG9a-kFLdxRfJF0UNpWkCxPircCw2twrBk0T0FlXoUTqx4wagafgE2yXg3Su5L8vp8mGDJOlJKusuZM4InBbLDG6CVOl0l_q/s400/key-3.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/333ZvjI" target="_blank">Membrane Keypad</a><br />
<br />
И проводочки<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh20TssU2VNDcj_NJqvSgzO5in1q3VgaYkB4R1GplDCOFSABo6nrmRhs4yDm-3mbODgBIu2jHsEtCdMtmJzRw3wyHC7bgzbkWLNSWP7bYHjAKZ7gv0DeYbhU5saWW7FxnLK1I_ZD6i1iDrl/s1600/wire-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh20TssU2VNDcj_NJqvSgzO5in1q3VgaYkB4R1GplDCOFSABo6nrmRhs4yDm-3mbODgBIu2jHsEtCdMtmJzRw3wyHC7bgzbkWLNSWP7bYHjAKZ7gv0DeYbhU5saWW7FxnLK1I_ZD6i1iDrl/s400/wire-1.jpg" width="400" /></a></div>
<br />
<a href="http://s.click.aliexpress.com/e/aUFQrv7" target="_blank">Female to Female Cable</a><br />
<br />
Соединяется всё в соответствии с изложенными ниже инструкциями.<br />
<br />
Arduino Nano --- Keyboard module<br />
GND --- GND<br />
D8 --- K1<br />
D9 --- K2<br />
D10 --- K3<br />
D11 --- K4<br />
<br />
Arduino Nano --- Transceiver module<br />
VCC --- VDD<br />
GND --- GND<br />
RX --- TXD<br />
TX --- RXD<br />
<br />
К ардуино уно, установленной на платформе, радиомодуль подключается аналогичным образом.<br />
<br />
Код для пульта<br />
<br />
<pre>////////////////////////
//
// Arduino Nano
//
////////////////////////
//
// Sketch: Transmitter
//
#include <util/delay.h>
void PORTB_Init( void )
{
// Port B
DDRB = 0b00000000;
PORTB = 0b00001111;
}
void PORTC_Init( void )
{
// Port C
DDRC = 0b00000000;
PORTC = 0b00000000;
}
void PORTD_Init( void )
{
// Port D
DDRD = 0b00000000;
PORTD = 0b00000000;
}
void USART_Init( void )
{
// Set baud rate (9600 bps)
UBRR0H = 0x00;
UBRR0L = 0x67;
// Enable receiver and transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Set frame format: 8 data, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}
unsigned char USART_Receive( void )
{
// Wait for data to be received
while ( !(UCSR0A & (1<<RXC0)) ) ;
// Get and return received data from buffer
return UDR0;
}
void USART_Transmit( unsigned char data )
{
// Wait for empty transmit buffer
while ( !( UCSR0A & (1<<UDRE0)) ) ;
// Put data into buffer, sends the data
UDR0 = data;
}
void setup()
{
cli();
PORTB_Init();
PORTC_Init();
PORTD_Init();
USART_Init();
sei();
}
void loop()
{
while (1)
{
if ( !(PINB & (1<<0)) )
{
_delay_ms(80);
USART_Transmit('f');
while ( !(PINB & (1<<0)) ) ;
}
else if ( !(PINB & (1<<1)) )
{
_delay_ms(80);
USART_Transmit('b');
while ( !(PINB & (1<<1)) ) ;
}
else if ( !(PINB & (1<<2)) )
{
_delay_ms(80);
USART_Transmit('l');
while ( !(PINB & (1<<2)) ) ;
}
else if ( !(PINB & (1<<3)) )
{
_delay_ms(80);
USART_Transmit('r');
while ( !(PINB & (1<<3)) ) ;
}
USART_Transmit('s');
_delay_ms(80);
}
}
//
// End
//
////////////////////////</pre>
<br />
Код для платформы<br />
<br />
<pre>////////////////////////
//
// Arduino Uno
//
////////////////////////
//
// Sketch: Receiver
//
const unsigned char IN1 = 12;
const unsigned char IN2 = 11;
const unsigned char IN3 = 10;
const unsigned char IN4 = 9;
void driver_init(void)
{
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
}
void stop(void)
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
void forward(void)
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void backward(void)
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
void left(void)
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
void right(void)
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void setup()
{
Serial.begin(9600);
driver_init();
stop();
}
void loop()
{
unsigned char data;
if (Serial.available() > 0)
{
data = Serial.read();
if ( data == 's' )
stop();
if ( data == 'f' )
forward();
if ( data == 'b' )
backward();
if ( data == 'l' )
left();
if ( data == 'r' )
right();
}
}
//
// End
//
////////////////////////</pre>
<br />
Назначение кнопок пульта:<br />
<br />
K1 --- движение вперед,<br />
K2 --- движение назад,<br />
K3 --- поворот налево,<br />
K4 --- поворот направо.<br />
<br />
Если не нажата ни одна кнопка, то платформа не двигается.<br />
<br />
Модули обеспечивают связь в пределах метров пяти точно. На большем расстоянии не было возможности проверить.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-83722010094087651942017-11-02T15:09:00.000-07:002017-11-02T15:30:07.831-07:00Рельсотрон<div dir="ltr" style="text-align: left;" trbidi="on">
Статья больше теоретическая. Идея. И приблизительные расчеты.<br />
<br />
<a name='more'></a><br />
Периодически мне попадаются материалы о пушке Гаусса. Статьи. Видео. Очень много самодельных конструкций. Эти пушки можно купить: <a href="http://s.click.aliexpress.com/e/Rniu3rR" target="_blank">ссылка1</a>, <a href="http://s.click.aliexpress.com/e/mq33bEU" target="_blank">ссылка2</a>. Есть более серьезные конструкции: <a href="http://s.click.aliexpress.com/e/IQVRBaU" target="_blank">ссылка3</a>. Есть совсем монстры: <a href="http://s.click.aliexpress.com/e/zZVFqJu" target="_blank">ссылка4</a>, <a href="http://s.click.aliexpress.com/e/aqzR76m" target="_blank">ссылка5</a>.<br />
<br />
А вот с рельсотронами всё иначе. Купить их непросто. Мне не попадались. Самодельных конструкций очень мало. И это специфичные конструкции.<br />
<br />
Вот я и решил сделать игрушечный рельсотрончик. Сам рельсотрон устроен достаточно просто.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiscSsoZvrY_SWkYmUjfKsSCBuxwVu4awm-j2sjbDznnrMEb8dQX43y6V3SCy-kZBJCYeBGC8tngB9tPtDqvJaow5i9JkL4JXwFJnlaD8GEzBycmWz6fj36_6nlBu4L8eyf2nFOllPnSMhZ/s1600/railgun_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="700" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiscSsoZvrY_SWkYmUjfKsSCBuxwVu4awm-j2sjbDznnrMEb8dQX43y6V3SCy-kZBJCYeBGC8tngB9tPtDqvJaow5i9JkL4JXwFJnlaD8GEzBycmWz6fj36_6nlBu4L8eyf2nFOllPnSMhZ/s400/railgun_2.png" width="400" /></a></div>
<br />
Рельсы, снаряд и мощный источник тока.<br />
<br />
Снаряд заставляет двигаться сила ампера. Чтобы уменьшить необходимый для стрельбы ток я решил добавить две электромагнитные катушки. Они должны создавать дополнительное магнитное поле перпендикулярно току текущему в снаряде и тем самым увеличивать силу ампера действующую на снаряд.<br />
<br />
Расчеты.<br />
<br />
Сила ампера<br />
<br />
F = B * I * L<br />
<br />
F - сила ампера (N)<br />
B - магнитная индукция (T)<br />
I - сила тока (A)<br />
L - длина проводника (m)<br />
<br />
Магнитной индукцией создаваемой рельсами я решил пренебречь. Основное магнитное поле у меня должны создавать катушки.<br />
<br />
Магнитная индукция соленоида<br />
<br />
B = Mo * M * I * N/L<br />
<br />
B - магнитная индукция (T)<br />
Mo - магнитная постоянная (H/m)<br />
M - относительная магнитная проницаемость среды <br />
I - ток в обмотке (A)<br />
N - число витков <br />
L - длина соленоида (m)<br />
<br />
Магнитная постоянная (магнитная проницаемость вакуума)<br />
Mo = 1.25663706 / 1000000.0 H/m<br />
<br />
Относительная магнитная проницаемость воздуха<br />
M = 1.00000037<br />
<br />
Зная силу действующую на снаряд можно рассчитать ускорение с которым будет двигаться снаряд.<br />
<br />
Второй закон Ньютона<br />
<br />
F = m * a<br />
<br />
a = F / m<br />
<br />
a - ускорение тела (m/(s*s))<br />
F - сила, приложенная к телу (N)<br />
m - масса тела (kg)<br />
<br />
Снаряд предполагалось сделать из алюминиевой проволочки.<br />
<br />
m = v * p<br />
<br />
m - масса тела (g)<br />
v - объем тела (cm*cm*cm)<br />
p - плотность (g/(cm*cm*cm))<br />
<br />
Плотность алюминия<br />
2.6989 g/(cm*cm*cm)<br />
<br />
Проволока по сути является цилиндром.<br />
<br />
Объём цилиндра<br />
<br />
v = 3.14 * r * r * h<br />
<br />
v - объём цилиндра (cm*cm*cm)<br />
r - радиус основания цилиндра (cm)<br />
h - высота цилиндра (cm)<br />
<br />
Зная ускорение тела можно рассчитать скорость тела и расстояние пройденное телом.<br />
<br />
Равноускоренное движение (начальная скорость равна нулю)<br />
<br />
V = a * t<br />
<br />
V - скорость тела (m/s)<br />
a - ускорение тела (m/(s*s))<br />
t - время (s)<br />
<br />
S = (a * t * t) / 2<br />
<br />
S - расстояние пройденное телом (m)<br />
a - ускорение тела (m/(s*s))<br />
t - время (s)<br />
<br />
И в данном проекте категорически нельзя обойтись без расчета энергии снаряда.<br />
<br />
Кинетическая энергия<br />
<br />
E = (m * V * V) / 2<br />
<br />
E - кинетическая энергия (J)<br />
m - масса тела (kg)<br />
V - скорость тела (m/s)<br />
<br />
Для удобства выполнения расчетов была написана простенькая программа на python.<br />
<br />
<pre>#!/usr/bin/env python
# coding: utf-8
# railgun
# bullet
r = 0.2 # cm
h = 5.0 # cm
p = 2.6989 # g/(cm*cm*cm)
l = 0.02 # m
Ib = 100.0 # A
# coil
Mo = 1.25663706 / 1000000.0 # H/m
M = 1.00000037
Ic = 100.0 # A
N = 200.0
L = 0.20 # m
# working time
t = 0.2 # s
print 'bullet'
print l, 'm'
print Ib, 'A'
print ''
print 'coil'
print Ic, 'A'
print N, 'loop of wire'
print L, 'm'
print ''
print 'working time'
print t, 's'
print ''
# calculate
print 'calculate'
B = Mo * M * Ic * (N / L)
print B, 'T'
F = B * Ib * l
print F, 'N'
v = 3.14 * r * r * h
m = v * p
print m, 'g'
a = F / (m / 1000.0)
print a, 'm/(s*s)'
V = a * t
print V, 'm/s'
S = (a * t * t) / 2.0
print S, 'm'
E = ((m / 1000.0) * V * V) / 2.0
print E, 'J'
raw_input('')
# C:/Python27/python.exe C:\railgun\railgun.py</pre>
<br />
Цифры.<br />
<br />
<pre>bullet
0.02 m
100.0 A
coil
100.0 A
200.0 loop of wire
0.2 m
working time
0.2 s
calculate
0.125663752496 T
0.251327504991 N
1.6949092 g
148.283757614 m/(s*s)
29.6567515229 m/s
2.96567515229 m
0.745355736639 J</pre>
<br />
Немного пояснений по полученным результатам.<br />
<br />
Снаряд должен быть сделан из алюминиевой проволоки диаметром 4 мм и длиной 5 см. Проволочка гнется буквой П. При этом область на которую должна действовать сила ампера составит 2 см. Остальное будет скользящими контактами.<br />
<br />
Через снаряд пойдет ток в 100 ампер. Это много для данного проекта.<br />
<br />
Катушки представлены одним соленоидом состоящем из 200 витков и имеющем длину 20 см. Через соленоид должен течь ток в 100 ампер. Вообще, токи снаряда и соленоида не обязаны быть одинаковы.<br />
<br />
Рельсотрон будет разгонять снаряд 0.2 секунды.<br />
<br />
Итак. За это время снаряд разгонится до 29.7 метров в секунду. И кинетическая энергия снаряда составит 0.75 джоуля. А длина рельсотрона получилась почти 3 метра!<br />
<br />
В приведенных расчетах не учтена масса факторов. Только я сильно сомневаюсь, что это улучшит юзабилити девайса.<br />
<br />
Увы. Игрушечный рельсотрончик я не сделаю.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-19364403130217181712017-02-23T12:52:00.000-08:002017-02-23T13:09:06.764-08:00Избегаем столкновений с препятствиями<div dir="ltr" style="text-align: left;" trbidi="on">
Я установил на платформу инфракрасные датчики препятствий. Статья об этих модулях. И, разумеется, в статье приводится код.<br />
<br />
<a name='more'></a><br />
Робот с ИК датчиками.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVQliu0yziO8msaLqVnx_mBZfWhbGB66htxi_yDyOTzjRj-Fz5OllRYjok5vcbm0pg79Kig5Ovf8i0CC9Cg1ZKWyXxG8HQax5GfPNVFTQm4OclDJOCDcavDETyZL-uKuxEJl5i-B5AvW3Z/s1600/robot_338.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVQliu0yziO8msaLqVnx_mBZfWhbGB66htxi_yDyOTzjRj-Fz5OllRYjok5vcbm0pg79Kig5Ovf8i0CC9Cg1ZKWyXxG8HQax5GfPNVFTQm4OclDJOCDcavDETyZL-uKuxEJl5i-B5AvW3Z/s400/robot_338.JPG" width="400" /></a></div>
<br />
Установлено три модуля.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCFvRbUr1CEEKZJmMmU87yzaJLGGqunYLZDjB-wgepOhSWjcjb_RZPngamu87QFJX1me3QvB2vcmLAVv0LI1mAUwyRS-yoUprR3t9pVqQhQNP4SuF4_UHxVzxoIMqeNOiAnRkFaZURdogR/s1600/bumper_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="397" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCFvRbUr1CEEKZJmMmU87yzaJLGGqunYLZDjB-wgepOhSWjcjb_RZPngamu87QFJX1me3QvB2vcmLAVv0LI1mAUwyRS-yoUprR3t9pVqQhQNP4SuF4_UHxVzxoIMqeNOiAnRkFaZURdogR/s400/bumper_1.jpg" width="400" /></a></div>
<br />
Этот датчик у меня давно. Я уже делал робота с этим модулем <a href="http://justforduino.blogspot.ru/2014/02/blog-post_23.html" target="_blank">http://justforduino.blogspot.ru/2014/02/blog-post_23.html</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV_9RZdWME4gOHLN27Jpo0edZKv9sxmTFJ62shoRaz6Ao0QH4BIAeloVamZOOzEvpFAQdqYLmts2aQDVDCFoCMzMNGThW_zVQ0RQpuill3w4tyAzBewbRjgWCYjZJl-9hj7QWe_fGb-ryX/s1600/bumper_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV_9RZdWME4gOHLN27Jpo0edZKv9sxmTFJ62shoRaz6Ao0QH4BIAeloVamZOOzEvpFAQdqYLmts2aQDVDCFoCMzMNGThW_zVQ0RQpuill3w4tyAzBewbRjgWCYjZJl-9hj7QWe_fGb-ryX/s400/bumper_2.jpg" width="400" /></a></div>
<br />
Недавно приобретенные мной датчики препятствий. Есть разные по конструкции, но внешне похожие реализации. На картинке показана версия на NE555. Я ещё видел на 74HC00D.<br />
<br />
Ранее купленные ИК модули лучше. Они обнаруживают препятствия с большего расстояния. Для моей платформы они также лучше подходят по размерам и креплению.<br />
<br />
Принципиальных отличий у показанных датчиков препятствий нет. Светодиод периодически мигает на определенной частоте. Отраженный от препятствий ИК свет регистрируется приемником.<br />
<br />
У модулей одинаковое число выводов. Назначение выводов также идентично.<br />
<br />
В этом проекте модули подключены к ардуино так, как описано ниже.<br />
<br />
Левый модуль.<br />
<br />
Arduino --- Infrared Sensor<br />
GND --- GND<br />
VCC --- +<br />
A0 --- OUT<br />
<br />
Центральный модуль.<br />
<br />
Arduino --- Infrared Sensor<br />
GND --- -<br />
VCC --- +<br />
A1 --- S<br />
<br />
Правый модуль.<br />
<br />
Arduino --- Infrared Sensor<br />
GND --- GND<br />
VCC --- +<br />
A2 --- OUT<br />
<br />
Когда препятствий нет, на выходах датчиков установлена логическая единица. При регистрации препятствия, на выходах модулей устанавливается логический ноль.<br />
<br />
Скетч<br />
<br />
<pre>////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Sketch: Robot
//
#include <util/delay.h>
#define DRIVER_DDR DDRB
#define DRIVER_PORT PORTB
#define ENA 5
#define IN1 4
#define IN2 3
#define IN3 2
#define IN4 1
#define ENB 0
#define BUMPER_DDR DDRC
#define BUMPER_PORT PORTC
#define BUMPER_PIN PINC
#define S1 2
#define S2 1
#define S3 0
volatile unsigned char count = 0;
volatile unsigned char width = 22;
void bumper_init( void );
void driver_init( void );
void tc2_init( void );
void stop( void );
void forward( void );
void backward( void );
void right( void );
void left( void );
void setup()
{
bumper_init();
driver_init();
tc2_init();
_delay_ms(4000);
}
void loop()
{
if ( (BUMPER_PIN & (1<<S1)) == 0 )
{
stop();
_delay_ms(1000);
right();
while ( (BUMPER_PIN & ((1<<S1)|(1<<S2)|(1<<S3))) !=
((1<<S1)|(1<<S2)|(1<<S3)) ) ;
_delay_ms(500);
stop();
_delay_ms(1000);
}
if ( (BUMPER_PIN & (1<<S3)) == 0 )
{
stop();
_delay_ms(1000);
left();
while ( (BUMPER_PIN & ((1<<S1)|(1<<S2)|(1<<S3))) !=
((1<<S1)|(1<<S2)|(1<<S3)) ) ;
_delay_ms(500);
stop();
_delay_ms(1000);
}
if ( (BUMPER_PIN & (1<<S2)) == 0 )
{
stop();
_delay_ms(1000);
if ( (TCNT2 & (1<<0)) == 0 )
{
right();
}
else
{
left();
}
while ( (BUMPER_PIN & ((1<<S1)|(1<<S2)|(1<<S3))) !=
((1<<S1)|(1<<S2)|(1<<S3)) ) ;
_delay_ms(500);
stop();
_delay_ms(1000);
}
forward();
while ( (BUMPER_PIN & ((1<<S1)|(1<<S2)|(1<<S3))) ==
((1<<S1)|(1<<S2)|(1<<S3)) ) ;
}
void bumper_init()
{
BUMPER_DDR &= ~((1<<S1)|(1<<S2)|(1<<S3));
BUMPER_PORT |= ((1<<S1)|(1<<S2)|(1<<S3));
}
void driver_init()
{
DRIVER_DDR |= ((1<<ENA)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4)|(1<<ENB));
DRIVER_PORT &= ~((1<<ENA)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4)|(1<<ENB));
}
void tc2_init()
{
// TC2 Counter Value Register
TCNT2 = 0;
// TC2 Control Register A
// COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
TCCR2A = 0;
// TC2 Control Register B
// FOC2A FOC2B - - WGM22 CS22 CS21 CS20
TCCR2B = (1<<CS20);
// TC2 Interrupt Mask Register
// - - - - - OCIE2B OCIE2A TOIE2
TIMSK2 = (1<<TOIE2);
// TC2 Interrupt Flag Register
// - - - - - OCF2B OCF2A TOV2
TIFR2 = (1<<TOV2);
}
void stop()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
}
void forward()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
}
void backward()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
}
void right()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
}
void left()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
}
ISR(TIMER2_OVF_vect)
{
if ( count == 0 ) DRIVER_PORT |= ((1<<ENA)|(1<<ENB));
if ( count == width ) DRIVER_PORT &= ~((1<<ENA)|(1<<ENB));
count += 1;
if ( count == 40 ) count = 0;
}
//
// End
//
////////////////////////</pre>
<br />
Проверка датчиков препятствий выполняется в основной функции. Сначала проверяется левый датчик. Если препятствие регистрируется, то выполняется поворот направо. Следующим проверяется правый датчик. Если препятствие регистрируется этим датчиком, то выполняется поворот налево. Последним проверяется центральный датчик. Если препятствие регистрируется центральным датчиком, то направление поворота зависит от значения нулевого бита счетного регистра таймера/счетчика 2. Если этот бит равен нулю, то робот поворачивает направо. В противном случае робот поворачивает налево. Вот такая реализация случайного поведения.<br />
<br />
Повороты выполняются до тех пор, пока датчики не перестают видеть препятствие плюс ещё 500 миллисекунд. Все изменения направления движения выполняются после остановки и неподвижного стояния в течении секунды.<br />
<br />
Пока препятствий нет, робот едет вперед.<br />
<br />
Итог. Не зря снижал скорость робота. Если бы робот двигался быстрее, то просто не успевал бы остановится. А так всё работает не плохо.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-51048392941472141872017-02-12T08:08:00.000-08:002017-02-12T08:08:03.939-08:00Снижаем скорость<div dir="ltr" style="text-align: left;" trbidi="on">
Эта статья про ШИМ (PWM). Именно с помощью широтно-импульсной модуляции я решил замедлить своего робота.<br />
<br />
<a name='more'></a><br />
Чтобы использовать ШИМ, необходимо немного изменить подключение драйвера двигателей к ардуино.<br />
<br />
arduino uno --- motor driver<br />
D8 --- ENB<br />
D9 --- IN4<br />
D10 --- IN3<br />
D11 --- IN2<br />
D12 --- IN1<br />
D13 --- ENA<br />
<br />
Скетч<br />
<br />
<pre>////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Sketch: Robot
//
// driver --- arduino
// ENA --- D13
// IN1 --- D12
// IN2 --- D11
// IN3 --- D10
// IN4 --- D9
// ENB --- D8
#include <util/delay.h>
#define DRIVER_DDR DDRB
#define DRIVER_PORT PORTB
#define ENA 5
#define IN1 4
#define IN2 3
#define IN3 2
#define IN4 1
#define ENB 0
volatile unsigned char count = 0;
volatile unsigned char width = 22;
void driver_init( void );
void tc2_init( void );
void stop( void );
void forward( void );
void backward( void );
void right( void );
void left( void );
void setup()
{
driver_init();
tc2_init();
_delay_ms(4000);
}
void loop()
{
forward();
_delay_ms(4000);
stop();
_delay_ms(1000);
backward();
_delay_ms(4000);
stop();
_delay_ms(1000);
right();
_delay_ms(4000);
stop();
_delay_ms(1000);
left();
_delay_ms(4000);
stop();
_delay_ms(1000);
}
void driver_init()
{
DRIVER_DDR |= ((1<<ENA)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4)|(1<<ENB));
DRIVER_PORT &= ~((1<<ENA)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4)|(1<<ENB));
}
void tc2_init()
{
// TC2 Counter Value Register
TCNT2 = 0;
// TC2 Control Register A
// COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
TCCR2A = 0;
// TC2 Control Register B
// FOC2A FOC2B - - WGM22 CS22 CS21 CS20
TCCR2B = (1<<CS20);
// TC2 Interrupt Mask Register
// - - - - - OCIE2B OCIE2A TOIE2
TIMSK2 = (1<<TOIE2);
// TC2 Interrupt Flag Register
// - - - - - OCF2B OCF2A TOV2
TIFR2 = (1<<TOV2);
}
void stop()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
}
void forward()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
}
void backward()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
}
void right()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
}
void left()
{
DRIVER_PORT &= ~((1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
DRIVER_PORT |= ((0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
}
ISR(TIMER2_OVF_vect)
{
if ( count == 0 ) DRIVER_PORT |= ((1<<ENA)|(1<<ENB));
if ( count == width ) DRIVER_PORT &= ~((1<<ENA)|(1<<ENB));
count += 1;
if ( count == 40 ) count = 0;
}
//
// End
//
////////////////////////</pre>
<br />
Приведенный скетч будет работать только в ардуино с микроконтроллером ATmega328 или ATmega168.<br />
<br />
В программе ШИМ реализован с помощью таймера/счетчика 2. Это восьмибитный таймер счетчик.<br />
<br />
Работа с таймером/счетчиком 2 осуществляется через специальные регистры. Изменение значений этих регистров, точнее, изменение битов этих регистров, влияет на работу таймера/счетчика 2. Содержимое регистров можно читать (присваивать значение регистра какой либо переменной).<br />
<br />
Если будет интерес к таймеру/счетчику 2, напишу про все его регистры и их биты. А пока ограничусь кратким описанием регистров и битов значимых для данного проекта.<br />
<br />
Чтобы понять как работает показанный код достаточно разобраться в регистрах:<br />
1) TCNT2 - TC2 Counter Value Register (счетный регистр таймера/счетчика 2);<br />
2) TCCR2A - TC2 Control Register A (первый управляющий регистр таймера/ счетчика 2);<br />
3) TCCR2B - TC2 Control Register B (второй управляющий регистр таймера/ счетчика 2);<br />
4) TIMSK2 - TC2 Interrupt Mask Register (регистр управления прерываниями таймера/счетчика 2);<br />
5) TIFR2 - TC2 Interrupt Flag Register (регистр флагов прерываний таймера/счетчика 2).<br />
<br />
Полагаю не будет лишним указать названия всех битов этих регистров.<br />
<br />
TCCR2A: COM2A1, COM2A0, COM2B1, COM2B0, -, -, WGM21, WGM20.<br />
TCCR2B: FOC2A, FOC2B, -, -, WGM22, CS22, CS21, CS20.<br />
TIMSK2: -, -, -, -, -, OCIE2B, OCIE2A, TOIE2.<br />
TIFR2: -, -, -, -, -, OCF2B, OCF2A, TOV2.<br />
<br />
Биты отмеченные как "-" не используются. Их значение ни на что не влияет.<br />
<br />
В регистре TCNT2 записано то, что насчитал таймер/счетчик 2. Это число от 0 до 255.<br />
<br />
Через регистры TCCR2A и TCCR2B осуществляется управление, настройка таймера/счетчика 2.<br />
<br />
Биты CS22, CS21, CS20 регистра TCCR2B отвечают за тактовый сигнал таймера/счетчика 2. Если все эти биты сброшены (в битах записаны нули), то таймер/счетчик 2 остановлен (отсутствует тактовый сигнал). Если установлен только бит CS20 (в этом бите записана единица, а в остальных битах записаны нули), то таймер/счетчик 2 работает на основной частоте контроллера (для arduino uno это 16 MHz). Этот режим тактирования таймера/счетчика 2 и используется в программе.<br />
<br />
В таком режиме значение счетного регистра таймера/счетчика 2 увеличивается на 1 за один такт микроконтроллера. Периодически происходит переполнение счетного регистра. Подробнее об этом процессе можно почитать на <a href="http://justforduino.blogspot.ru/2013/12/blog-post.html" target="_blank">http://justforduino.blogspot.ru/2013/12/blog-post.html</a><br />
<br />
Регистр TIMSK2 отвечает за прерывания таймера/счетчика 2.<br />
<br />
Бит TOIE2 регистра TIMSK2 разрешает или запрещает прерывание по переполнению таймера/счетчика 2. Если бит сброшен (ноль), то прерывание запрещено. А если бит установлен (единица), то прерывание разрешено.<br />
<br />
Регистр TIFR2 отведен для флагов прерываний. Значения битов этого регистра меняются самим контроллером. При возникновении события прерывания, устанавливается соответствующий прерыванию флаг (в соответствующий бит записывается единица). При вызове обработчика прерывания, соответствующий прерыванию флаг сбрасывается (в соответствующий бит записывается ноль). Флаг прерывания можно сбросить программно. Для этого нужно записать единицу в бит соответствующий прерыванию.<br />
<br />
В программе используется прерывание по переполнению таймера/счетчика 2. Под флаг этого прерывания отведен бит TOV2 регистра TIFR2.<br />
<br />
Обрабатывается прерывание по переполнению таймера/счетчика 2 в ISR(TIMER2_OVF_vect).<br />
<br />
Обработчик прерывания по переполнению таймера/счетчика 2 вызывается через<br />
<br />
(1.0 / 16000000.0) * 256.0 * 1000.0 = 0.016 ms<br />
<br />
Для формирования одного периода ШИМ необходимо вызвать обработчик 40 раз<br />
<br />
(1.0 / 16000000.0) * 256.0 * 1000.0 * 40.0 = 0.64 ms<br />
<br />
Таким образом частота ШИМ получается<br />
<br />
1.0 / 0.64 = 1.5625 KHz<br />
<br />
В результате работы программы на цифровых пинах 8 и 13 будет сигнал показанный на представленной ниже картинке<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjSXEjRjZnQxKEf4bJxr-d3sUJTH6a2YUsSUYjr76CC4rXX4JqOosng-UtxZMtVkyEVXVk82lpVy2VzNyFLWCk3Y4GXb0-jZzfFUAGFtt4fsH36bGy11kAcfjH3lPEkkiGG72ex-06Ph-m/s1600/controller.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjSXEjRjZnQxKEf4bJxr-d3sUJTH6a2YUsSUYjr76CC4rXX4JqOosng-UtxZMtVkyEVXVk82lpVy2VzNyFLWCk3Y4GXb0-jZzfFUAGFtt4fsH36bGy11kAcfjH3lPEkkiGG72ex-06Ph-m/s400/controller.png" width="400" /></a></div>
<br />
На клеммах электродвигателя ток меняется приблизительно так, как показано на картинке ниже<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggNRXVOqEk3gP34IJ1BVofoiWjv9xLq3MeSjjtxFD6TFHbPc2CCC3MZlxyrGwrNOhgT5UjDND3bYsFozwyPEPGquyNTz9Bef_T3fLVp7KfbBrZD0MuIoSbHky7IQ2B1w9-pNTLVbd5ytgI/s1600/motor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggNRXVOqEk3gP34IJ1BVofoiWjv9xLq3MeSjjtxFD6TFHbPc2CCC3MZlxyrGwrNOhgT5UjDND3bYsFozwyPEPGquyNTz9Bef_T3fLVp7KfbBrZD0MuIoSbHky7IQ2B1w9-pNTLVbd5ytgI/s400/motor.png" width="400" /></a></div>
<br />
Это связано с индуктивностью обмоток электродвигателя. И это накладывает ограничения на частоту ШИМ. Если частота будет слишком высокая, то ток в обмотках не будет достигать максимально возможного значения. В итоге сильно снизится момент двигателя.<br />
<br />
От значения переменной width зависит заполнение ШИМ. Этой переменной можно присвоить значение от 0 до 40. Опытным путем была установлена нецелесообразность присвоения значения менее 22. Дело в том, что снижение заполнения приводит к снижению момента на валу коллекторного двигателя постоянного тока. Проще говоря, платформа перестает ехать.<br />
<br />
Нужно учитывать ещё один нюанс. Двигатели получают ток непосредственно от аккумулятора. А аккумулятор в процессе работы постепенно разряжается. Напряжение и ток снижаются. Момент на валу также снижается.<br />
<br />
Итог. Полученный результат меня вполне устраивает.<br />
<br />
К сожалению видео снять проблематично. Снег, холод. Может позже.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-33254915608477513122017-02-04T15:35:00.000-08:002017-02-05T14:05:55.728-08:00Настоящий робот<div dir="ltr" style="text-align: left;" trbidi="on">
В этой статье я расскажу об электронике установленной на мою новую платформу. Также здесь приведен простой тестовый скетч.<br />
<br />
<a name='more'></a><br />
Фотография робота<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj73Fpjp3pvA29Yfga0AAHgiCqsoK3AH6ydNTrcaAdE6EuBYBNGv1y2j8EX8H7E9LYMo31bEzFyBj1Me-hVmlm2ZIid5oe54_cgesPL1TkMBMxM8EQclvMiPAFh_tZHlnigyMwuY9UTzRPR/s1600/robot_316.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj73Fpjp3pvA29Yfga0AAHgiCqsoK3AH6ydNTrcaAdE6EuBYBNGv1y2j8EX8H7E9LYMo31bEzFyBj1Me-hVmlm2ZIid5oe54_cgesPL1TkMBMxM8EQclvMiPAFh_tZHlnigyMwuY9UTzRPR/s400/robot_316.JPG" width="400" /></a></div>
<br />
Сейчас управление роботом возложено на Arduino UNO<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguSOyH4ToY9yrUufyMbvJIxTtQf5-NT4U6JvCsI5eFD5oVARYmrsBrJdoo_teqdPPhgEIjOLGPTgVrxK__Eu_V1K2P65v2e4ahpWsI9y07VpRqppFOTQa-fonMQuvMBf9X8X1bn7dk9LL3/s1600/arduino.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguSOyH4ToY9yrUufyMbvJIxTtQf5-NT4U6JvCsI5eFD5oVARYmrsBrJdoo_teqdPPhgEIjOLGPTgVrxK__Eu_V1K2P65v2e4ahpWsI9y07VpRqppFOTQa-fonMQuvMBf9X8X1bn7dk9LL3/s400/arduino.jpg" width="400" /></a></div>
<br />
Для более комфортной работы с ардуино, используется Arduino Sensor Shield v5.0<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5vEaflIe8sQS4_G6-VlDA84WGc-mn1CBfbNYNVmAvx6krmqqN14yhBeb5n_Sae4shi9Kjvfe4Hpdf-gteg2G5PP6d4qSS3mdBNq410fWQGHPd2CwrBOMJx9uJHyhxgGDxjLgtGW_Phzvc/s1600/shield.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5vEaflIe8sQS4_G6-VlDA84WGc-mn1CBfbNYNVmAvx6krmqqN14yhBeb5n_Sae4shi9Kjvfe4Hpdf-gteg2G5PP6d4qSS3mdBNq410fWQGHPd2CwrBOMJx9uJHyhxgGDxjLgtGW_Phzvc/s400/shield.jpg" width="400" /></a></div>
<br />
Драйвер двигателей на L298N<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzDoFlFmbnF4ZWn3Wl-SxX2eHdkc_lAw3sHmp4usNTGTj0exdxqrQIaqL13yB5VpFB5qFX92jDQhb9E70RxamVvk3xOPzCW-jxq82vvQ_bfdPM-UlZCh16cu6n-8XQ7Kc6Ulo_0vHg5SzP/s1600/l298n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzDoFlFmbnF4ZWn3Wl-SxX2eHdkc_lAw3sHmp4usNTGTj0exdxqrQIaqL13yB5VpFB5qFX92jDQhb9E70RxamVvk3xOPzCW-jxq82vvQ_bfdPM-UlZCh16cu6n-8XQ7Kc6Ulo_0vHg5SzP/s400/l298n.jpg" width="400" /></a></div>
<br />
Закреплено всё на нейлоновых стойках<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFfDMRSuuAF4YMZpZwlJSuVFJ1FoPSraG_85jlkkU2QLS9pQMAl2aOmYvd8yM-WPsGxWZCo5pYpR4Oh1qLJ48pWjK3e95dvUAKSi2j5Q-7wiJbo-Dm_xMsF3wgeSe39FfhGWlgGBTsazIj/s1600/hex_nylon.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFfDMRSuuAF4YMZpZwlJSuVFJ1FoPSraG_85jlkkU2QLS9pQMAl2aOmYvd8yM-WPsGxWZCo5pYpR4Oh1qLJ48pWjK3e95dvUAKSi2j5Q-7wiJbo-Dm_xMsF3wgeSe39FfhGWlgGBTsazIj/s400/hex_nylon.jpg" width="400" /></a></div>
<br />
Источником энергии служит аккумулятор LiPo 3S 1600mAh<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTJW69AOJzjCvXUTdCZ7sfG9PhaxDdPVBtfSfwf1xi6sv9R40ieVZa6KShRH5NDjcfNQHOg3nUUv1TJ5K1N5lvoEOOEuX0lxv_ZntCxL8RuOyLERFEYcIczqrPqYGdU4qf37s53n_Py44g/s1600/zippy-lipo-3s-1600mah.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTJW69AOJzjCvXUTdCZ7sfG9PhaxDdPVBtfSfwf1xi6sv9R40ieVZa6KShRH5NDjcfNQHOg3nUUv1TJ5K1N5lvoEOOEuX0lxv_ZntCxL8RuOyLERFEYcIczqrPqYGdU4qf37s53n_Py44g/s400/zippy-lipo-3s-1600mah.png" width="400" /></a></div>
<br />
Компактные, легкие, ёмкие. Но пожароопасные и взрывоопасные.<br />
<br />
Хранить и заряжать их следует в специальных защитных пакетах.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-cUPh7dqFaQKXdBfCUPVF46sesnxxhY5f7Bd1uTOwpKRfSKfVhd3cTUUvdE1klEloMdEbCBbWC-ILPaNlY-ZtuSqN-zUkk69-KwxQNcMbPU0q54uGsOqzAxW2g7B2iTqQBO0aT49pe1Fv/s1600/bag.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-cUPh7dqFaQKXdBfCUPVF46sesnxxhY5f7Bd1uTOwpKRfSKfVhd3cTUUvdE1klEloMdEbCBbWC-ILPaNlY-ZtuSqN-zUkk69-KwxQNcMbPU0q54uGsOqzAxW2g7B2iTqQBO0aT49pe1Fv/s400/bag.jpg" width="400" /></a></div>
<br />
Литий полимерные аккумуляторы настоятельно не рекомендуется эксплуатировать без специальных устройств контроля напряжения<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaGEv-BujzCP9l4iIn3GC2jZ1ghfGdlUp_Xa6YGue8FjhZm3m2uTsupILZucK_Vwa1NbNWfcIdijnUjkYvRSJNgwKWXtbuloDrfyagLeo6JedtlI4irVfZb2C4PrTjoFPetq3V6XzOKD3_/s1600/lipo_alarm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaGEv-BujzCP9l4iIn3GC2jZ1ghfGdlUp_Xa6YGue8FjhZm3m2uTsupILZucK_Vwa1NbNWfcIdijnUjkYvRSJNgwKWXtbuloDrfyagLeo6JedtlI4irVfZb2C4PrTjoFPetq3V6XzOKD3_/s400/lipo_alarm.jpg" width="400" /></a></div>
<br />
Литий полимерные аккумуляторы, зарядные устройства для них и прочее связанное с литиевыми аккумуляторами лучше покупать на <a href="https://hobbyking.com/" target="_blank">https://hobbyking.com/</a><br />
<br />
Последствия неправильного обращения с литиевыми аккумуляторами можно увидеть на <a href="http://youtube.com/" target="_blank">http://youtube.com/</a> Ищите по ключевым словам lipo и fire.<br />
<br />
Подключается всё в соответствии с изложенными ниже инструкциями.<br />
<br />
arduino uno --- motor driver<br />
D9 --- IN4<br />
D10 --- IN3<br />
D11 --- IN2<br />
D12 --- IN1<br />
<br />
motor driver --- left motor<br />
OUT3 --- M1 (зеленый провод)<br />
OUT4 --- M2 (черный провод)<br />
<br />
motor driver --- right motor<br />
OUT2 --- M1 (зеленый провод)<br />
OUT1 --- M2 (черный провод)<br />
<br />
motor driver --- battery (12V)<br />
GND --- минус батареи (черный провод)<br />
+12V --- плюс батареи (красный провод)<br />
<br />
На батарее используется разъем XT60<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggFVtj5yIadDA6UM-h-suuz7CfI1r1nxt09MTXuH-xhSSmP_Hb2TOOEn5Av_1HI6pzCUkYffcxOnaDTprHPY4XLaEeDOv4kJ25ssmMpDlUQRUa8CG0k6rFOlJnvfXlqZ-sg7_jgT_97d7o/s1600/XT60.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggFVtj5yIadDA6UM-h-suuz7CfI1r1nxt09MTXuH-xhSSmP_Hb2TOOEn5Av_1HI6pzCUkYffcxOnaDTprHPY4XLaEeDOv4kJ25ssmMpDlUQRUa8CG0k6rFOlJnvfXlqZ-sg7_jgT_97d7o/s400/XT60.jpg" width="400" /></a></div>
<br />
Мне паять было лень и я подключил батарею через маленькие крокодильчики. Ток небольшой. Всё работает. Но нужна осторожность. Если устроить короткое замыкание литиевой батарее, то мало не покажется.<br />
<br />
К ардуино батарея подключается через Power Plug Connector Adapter 2.1*5.5 mm<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz4AdfYydVudyglhCTxV-cwntWQSaqx6n842I-GD9eR1pdh904y8CyDD1DnP2NvMRK0CZyWTbu9PvBTTodefvHBi6eE0ws7CM1dKaVqekCwlYLYv4rBtVNL1Dlq7DAHPneGYVxypa6JLfQ/s1600/connector.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz4AdfYydVudyglhCTxV-cwntWQSaqx6n842I-GD9eR1pdh904y8CyDD1DnP2NvMRK0CZyWTbu9PvBTTodefvHBi6eE0ws7CM1dKaVqekCwlYLYv4rBtVNL1Dlq7DAHPneGYVxypa6JLfQ/s400/connector.jpg" width="400" /></a></div>
<br />
Точных измерений я не проводил. Однако некоторые приблизительные расчеты думаю следует привести.<br />
<br />
При потреблении 350 миллиампер одним двигателем, получится 1400 миллиампер для четырех моторов. Если остальной электронике отвести 200 миллиампер, в сумме будет 1600 миллиампер. С аккумулятором на 1600mAh робот сможет непрерывно передвигаться около часа.<br />
<br />
Аккумулятор способный отдать большой ток, вроде использованного мной, не нужен. Если бы я покупал аккумулятор специально для этой платформы, то взял бы Zippy LiFePo4 3s 9.9v 1800mAh 5c. Эти аккумуляторы более безопасны.<br />
<br />
Скетч<br />
<br />
<pre>////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Sketch: Robot
//
#include <util/delay.h>
const unsigned char IN1 = 12;
const unsigned char IN2 = 11;
const unsigned char IN3 = 10;
const unsigned char IN4 = 9;
void motors_init();
void stop();
void forward();
void backward();
void right();
void left();
void setup()
{
motors_init();
stop();
_delay_ms(4000);
}
void loop()
{
forward();
_delay_ms(2000);
stop();
_delay_ms(1000);
backward();
_delay_ms(2000);
stop();
_delay_ms(1000);
right();
_delay_ms(2000);
stop();
_delay_ms(1000);
left();
_delay_ms(2000);
stop();
_delay_ms(1000);
}
void motors_init()
{
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
}
void stop()
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
void forward()
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void backward()
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
void right()
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void left()
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
//
// End
//
////////////////////////</pre>
<br />
Выполняется программа следующим образом. После подачи питания робот стоит на месте четыре секунды. Затем робот едет вперед две секунды. Останавливается и стоит одну секунду. Затем едет назад две секунды. Останавливается и снова стоит одну секунду. Дальше робот поворачивает направо в течении двух секунд. Затем стоит одну секунду. Потом поворачивает налево в течении двух секунд. Опять останавливается на одну секунду. И всё повторяется начиная с движения вперед.<br />
<br />
Этот скетч дает возможность визуально оценить скорость движения, скорость поворота.<br />
<br />
Платформа получилась более быстрой, чем хотелось. Нужно будет её немного замедлить.<br />
<br />
И таки да. Это уже настоящий мобильный робот.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-19099184841433933712017-01-29T14:38:00.000-08:002017-01-29T14:38:20.174-08:00Моторы с энкодерами и редукторами<div dir="ltr" style="text-align: left;" trbidi="on">
Небольшая статья о приводах моей новой платформы.<br />
<br />
<a name='more'></a><br />
Фото 1<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiShW5fTvxM8fsFyaMNLQ8KHHpMstBMeF1c0qKb5Q0bR-7X66T-xTa6KBuNw1Eky9R9JlbFo0UF6aaI1SUBK3Heorcoew_-RVdam3Pq93MQHTWrMaqJiVBGFTY7X_o9lXW9sqY_mQIeksH3/s1600/motor1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiShW5fTvxM8fsFyaMNLQ8KHHpMstBMeF1c0qKb5Q0bR-7X66T-xTa6KBuNw1Eky9R9JlbFo0UF6aaI1SUBK3Heorcoew_-RVdam3Pq93MQHTWrMaqJiVBGFTY7X_o9lXW9sqY_mQIeksH3/s400/motor1.jpg" width="400" /></a></div>
<br />
Фото 2<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQgk3xCh1H-BbVQM72Eq9P662H3e-XKpIEEjFc-7n6OG0ADGfJ7GQsKgI0xRE3GBGeIL_3RS6U_dIsTQ9DXaanjIA6faY757UTL05NgV9iPdlmjcuQO1LZ_buWKKuuafwxracULK6o8u9g/s1600/motor2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="327" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQgk3xCh1H-BbVQM72Eq9P662H3e-XKpIEEjFc-7n6OG0ADGfJ7GQsKgI0xRE3GBGeIL_3RS6U_dIsTQ9DXaanjIA6faY757UTL05NgV9iPdlmjcuQO1LZ_buWKKuuafwxracULK6o8u9g/s400/motor2.jpg" width="400" /></a></div>
<br />
Размеры<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbj0lYvcDbfRqAt8fypvhqOP3XknaSFXYR0KBveApideH6rrYOahxSS81oWZrBIc8F0x3DP3inYsFww0LjzkByBTDWes5RzMFfPDGflToKLuEsgmtqatbXcwKWMB93DZ-83PYAqIUeTHZ/s1600/motor3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="167" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbj0lYvcDbfRqAt8fypvhqOP3XknaSFXYR0KBveApideH6rrYOahxSS81oWZrBIc8F0x3DP3inYsFww0LjzkByBTDWes5RzMFfPDGflToKLuEsgmtqatbXcwKWMB93DZ-83PYAqIUeTHZ/s400/motor3.jpg" width="400" /></a></div>
<br />
(вид сбоку)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEwVKMCmWW9YYNzaGCw0HYvjq5afp83sVADeRs7IdR0kZiyrZo1lJ9sEjT4V8YAiI6y5AeUOA_TyZJEO4oqA01yUEGzl7tTPavpLeGAKZhFVkk6WLUZeOn1aRkpsRsyzT4cuMj8IpS_C4q/s1600/motor4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEwVKMCmWW9YYNzaGCw0HYvjq5afp83sVADeRs7IdR0kZiyrZo1lJ9sEjT4V8YAiI6y5AeUOA_TyZJEO4oqA01yUEGzl7tTPavpLeGAKZhFVkk6WLUZeOn1aRkpsRsyzT4cuMj8IpS_C4q/s320/motor4.jpg" width="283" /></a></div>
<br />
(вид спереди)<br />
<br />
Коллекторные электродвигатели постоянного тока с датчиками угла поворота и редукторами.<br />
<br />
Куплены приводы были у <a href="https://ru.aliexpress.com/store/603733" target="_blank">Shenzhen ASLONG Motor Co., Ltd</a><br />
<br />
Ссылка на сами моторы: <a href="https://ru.aliexpress.com/item/JGB37-520B-With-encoder-Gear-motor-DC-gear-motor-Encoder-speed-with-encoder-A-B-phase/32698299894.html" target="_blank">https://ru.aliexpress.com/item/JGB37-520B-With-encoder-Gear-motor-DC-gear-motor-Encoder-speed-with-encoder-A-B-phase/32698299894.html</a><br />
<br />
По этой ссылке продается несколько различных вариантов приводов.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPfoBqkmJsVdLj7TVOz_cByNauy-RstpaBMZt_3IlvFOtYy1Ef754xUTxPm98Ro99EbCmbUcctJUBvz3exQ7WlCLj5eV5MxSKuZxSyWq5yR6VWq-lBLx7dr_ytiSkYI0JjrlgwUWKLeEnO/s1600/table.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPfoBqkmJsVdLj7TVOz_cByNauy-RstpaBMZt_3IlvFOtYy1Ef754xUTxPm98Ro99EbCmbUcctJUBvz3exQ7WlCLj5eV5MxSKuZxSyWq5yR6VWq-lBLx7dr_ytiSkYI0JjrlgwUWKLeEnO/s400/table.jpg" width="400" /></a></div>
<br />
Основные отличия в частоте вращения выходного вала и развиваемом моменте.<br />
<br />
Можно подобрать наиболее подходящий для своего проекта.<br />
<br />
Купленные мной моторы должны работать в диапазоне от 6 до 15 вольт. Но рекомендуется эксплуатация при 12 вольтовом питании. При этом без нагрузки мотор будет потреблять 120 миллиампер и обороты выходного вала составят 111 в минуту. Под нагрузкой мотору потребуется 350 миллиампер при моменте в 3.4 килограмма на сантиметр и 88 оборотах в минуту. Мощность на выходе должна составить 3 ватта. КПД получается 0.7 = (3.0 / (12.0 * 0.350). При заблокированном вале потребляемый ток достигнет 1 ампера, а момент увеличится до 13 килограмм на сантиметр. Редуктор имеет передаточное отношение 1 к 90 и длину в 24 миллиметра. Масса мотора с энкодером и редуктором составляет около 188 грамм.<br />
<br />
Энкодер состоит из многополюсного магнита закрепленного на валу электродвигателя и платки с двумя датчиками холла припаянной к выводам мотора. Схема платки довольно проста.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho-JX3Lpxx5PRnhN7Tq3OfoiC_Zzu1-4kZgNwRl_YraBJbyyB3mV0-ra4RRf0zHIX6isjnx7SSSRNONSzTPwke2ewlb9BqghJogGdfO85RMFew0bUGir6H85jIX2otPVXOCvXuVoU6VQ3z/s1600/encoder.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="373" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho-JX3Lpxx5PRnhN7Tq3OfoiC_Zzu1-4kZgNwRl_YraBJbyyB3mV0-ra4RRf0zHIX6isjnx7SSSRNONSzTPwke2ewlb9BqghJogGdfO85RMFew0bUGir6H85jIX2otPVXOCvXuVoU6VQ3z/s400/encoder.png" width="400" /></a></div>
<br />
IC1, IC2 - датчики холла. Судя по всему, внутренняя структура датчиков схожа с A3144. R1, R2 - подтягивающие резисторы на 3300 ом. R3 - токоограничительный резистор на 3300 ом. LED1 - красный индикаторный светодиод.<br />
<br />
Два датчика холла нужно для того, чтобы была возможность определения направления вращения вала мотора.<br />
<br />
Проверить работу энкодера можно с помощью совсем простой схемы.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVDxaQw4vw341_CjKhFr5MKl2hrICFJ94fIo8HBULYGDxQWZlgynRh2HG0ZFEHtwgBMu4TEyGDa4smqVMHEunoj_wC22dRJYzoJVoaXF89LZr5eszgpforEWjNLsu-LQbxop5ZvT5IZOIv/s1600/test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVDxaQw4vw341_CjKhFr5MKl2hrICFJ94fIo8HBULYGDxQWZlgynRh2HG0ZFEHtwgBMu4TEyGDa4smqVMHEunoj_wC22dRJYzoJVoaXF89LZr5eszgpforEWjNLsu-LQbxop5ZvT5IZOIv/s320/test.png" width="320" /></a></div>
<br />
Если крутить магнитный диск, то светодиоды будут загораться и гаснуть.<br />
<br />
На один оборот вала электродвигателя получается по 11 импульсов с каждого датчика холла.<br />
<br />
Таким образом на один оборот выходного вала будет 990 импульсов.<br />
<br />
11.0 * 90.0 = 990.0<br />
<br />
Это один импульс на 0.36 градуса.<br />
<br />
360.0 / (11.0 * 90.0) = 0.3636<br />
<br />
При 111 оборотах в минуту получается 546 микросекунд между двумя импульсами.<br />
<br />
(1.0 / (990.0 * (111.0 / 60.0))) * 1000000.0 = 546.0<br />
<br />
Не много.<br />
<br />
Скажу несколько слов о подключении. В комплекте уже есть кабель с разъемом. И контакты разъема на платке подписаны.<br />
<br />
У меня всё выглядит так:<br />
M1 --- зеленый провод,<br />
GND --- оранжевый провод,<br />
C1 --- желтый провод,<br />
C2 --- белый провод,<br />
3.3V --- красный провод,<br />
M2 --- черный провод.<br />
<br />
Подключается всё согласно нижеизложенным инструкциям.<br />
<br />
M1, M2 - питание двигателя (12 вольт).<br />
GND, 3.3V - питание датчика.<br />
C1, C2 - данные датчика.<br />
<br />
Устройство китайское. Поэтому перед подключением стоит его проверить. Хотя бы омметром.<br />
<br />
Подведу итог. В общем решение не плохое. Однако сейчас можно найти вариант с бесколлекторным двигателем постоянного тока. Такой привод лучше, но существенно дороже.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-26914621902043825422017-01-28T10:44:00.000-08:002017-01-28T10:58:10.476-08:00Сравнение скорости реакции<div dir="ltr" style="text-align: left;" trbidi="on">
Устройство описываемое в этой статье является модификацией ранее представленного. Почитать про первую версию можно на <a href="http://justforduino.blogspot.ru/2016/02/blog-post.html" target="_blank">http://justforduino.blogspot.ru/2016/02/blog-post.html</a><br />
<br />
<a name='more'></a><br />
Устройство не новое. Поэтому начну сразу со схемы.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioLuBGOWJqARMTTolAj7rr7VN_zsLvn6S9ehjfUfR41f4_PZdw2YMyCtFllOWbxKFPmJ86Eek6AFVBLdPeLQIvKm8wLUgRioBXYlwMgDjSthXCM5hFLjhRLxLZC51BFF_VG0aUbwQ_QODF/s1600/schematic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioLuBGOWJqARMTTolAj7rr7VN_zsLvn6S9ehjfUfR41f4_PZdw2YMyCtFllOWbxKFPmJ86Eek6AFVBLdPeLQIvKm8wLUgRioBXYlwMgDjSthXCM5hFLjhRLxLZC51BFF_VG0aUbwQ_QODF/s400/schematic.png" width="273" /></a></div>
<br />
Всё просто. Ардуино нано. Индикаторный светодиод. Токоограничительный резистор на 220 ом. Две кнопочки.<br />
<br />
Кнопок может быть от одной до шести. Подключаются к аналоговым пинам ардуино.<br />
<br />
Скетч для плат ардуино с контроллером ATmega328 / ATmega168.<br />
<br />
<pre>////////////////////////
//
// Arduino
//
////////////////////////
//
// Sketch:
//
// LED --- Digital Pin 8
// BUTTON 1 --- Analog Pin 0
// BUTTON 2 --- Analog Pin 1
// BUTTON 3 --- Analog Pin 2
// BUTTON 4 --- Analog Pin 3
// BUTTON 5 --- Analog Pin 4
// BUTTON 6 --- Analog Pin 5
unsigned char cheater = 0;
unsigned char button = 0;
unsigned long int time1 = 0;
unsigned long int time2 = 0;
void setup()
{
// Led initialization
DDRB = 0b00000001;
PORTB = 0b00000001;
// Buttons initialization
DDRC = 0b00000000;
PORTC = 0b00111111;
// UART initialization
Serial.begin(9600);
// Pseudo-random number generator initialization
cheater = ~PINC;
PORTB = 0b00000000; // LED ON
do { button = (PINC | cheater) & 0b00111111; }
while ( button == 0b00111111 );
randomSeed(micros());
PORTB = 0b00000001; // LED OFF
}
void loop()
{
Serial.println("round");
PORTB = 0b00000001; // LED OFF
delay(random(2000, 5000)); // wait
cheater = ~PINC;
PORTB = 0b00000000; // LED ON
time1 = micros();
do { button = (PINC | cheater) & 0b00111111; }
while ( button == 0b00111111 );
time2 = micros();
if ( (cheater & 0b00000001) != 0 )
Serial.println("1 cheater");
if ( (cheater & 0b00000010) != 0 )
Serial.println("2 cheater");
if ( (cheater & 0b00000100) != 0 )
Serial.println("3 cheater");
if ( (cheater & 0b00001000) != 0 )
Serial.println("4 cheater");
if ( (cheater & 0b00010000) != 0 )
Serial.println("5 cheater");
if ( (cheater & 0b00100000) != 0 )
Serial.println("6 cheater");
if ( (cheater & 0b00000001) == 0 && (button & 0b00000001) == 0 )
Serial.print("1 ");
if ( (cheater & 0b00000010) == 0 && (button & 0b00000010) == 0 )
Serial.print("2 ");
if ( (cheater & 0b00000100) == 0 && (button & 0b00000100) == 0 )
Serial.print("3 ");
if ( (cheater & 0b00001000) == 0 && (button & 0b00001000) == 0 )
Serial.print("4 ");
if ( (cheater & 0b00010000) == 0 && (button & 0b00010000) == 0 )
Serial.print("5 ");
if ( (cheater & 0b00100000) == 0 && (button & 0b00100000) == 0 )
Serial.print("6 ");
Serial.println(((time2-time1)/1000000.0), 6);
}
//
// End
//
////////////////////////</pre>
<br />
При подаче питания загорается светодиод. Нажатие на любую кнопку гасит светодиод. При этом происходит инициализация генератора псевдослучайных чисел. Теперь, как только светодиод вспыхнет, нужно быстро нажимать кнопки.<br />
<br />
Результаты можно посмотреть в мониторе порта ардуино.<br />
<br />
В программе частично реализована борьба с читерством. Если нажать и не отпускать кнопку, то в мониторе порта появится соответствующая надпись.<br />
<br />
Если все решат читерить, то придется перезапустить ардуино ресетом. При наличии большого желания такое развитие событий тоже можно предусмотреть в коде.<br />
<br />
Если нажать и отпустить кнопку пока светодиод не горит, то такое событие программа не заметит. Если бороться с читерством, то оценку таких действий также следует предусмотреть в программе.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-70798643165453135832017-01-11T05:47:00.001-08:002017-01-11T06:12:45.045-08:00Ещё одна робоплатформа<div dir="ltr" style="text-align: left;" trbidi="on">
В этот раз конструкция более надежная. Никакого скотча, изоленты и подобного. Все детальки покупные. Поэтому платформу легко повторить.<br />
<br />
<a name='more'></a><br />
Готовую платформу покупать не стал. Решил собрать свою конструкцию.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiycXoq5NiaWuKZBmGhIJHxtJnY3WOYEGa67u-z-H2OSQU_51AbHkaj6fu9XNgSgz93GtsoIzLzZGDI3ObtYDFY-HXfUJAApFbjwm_3YGBuOrl6fusTth00BQ3PEcS529iG3ljG5-CKIsZO/s1600/IMG_0291.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiycXoq5NiaWuKZBmGhIJHxtJnY3WOYEGa67u-z-H2OSQU_51AbHkaj6fu9XNgSgz93GtsoIzLzZGDI3ObtYDFY-HXfUJAApFbjwm_3YGBuOrl6fusTth00BQ3PEcS529iG3ljG5-CKIsZO/s400/IMG_0291.JPG" width="400" /></a></div>
<br />
Начну с перечня продавцов, у которых покупались детали.<br />
<br />
1) <a href="https://ru.aliexpress.com/store/1912455" target="_blank">iHardware</a><br />
2) <a href="https://ru.aliexpress.com/store/1471380" target="_blank">Robot love</a><br />
3) <a href="https://ru.aliexpress.com/store/603733" target="_blank">Shenzhen ASLONG Motor Co., Ltd</a><br />
<br />
Настоятельно рекомендую пользоваться доставкой China Post Registered Air Mail. Посылка будет отслеживаться везде, а не только в Китае.<br />
<br />
Собственно сами детальки.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGiHjqxS_uSHpESOM5q3u0VAxW8KdC9kgGcK9gtiN7tIDLOHK4blQ_3LuYeFCTehbtuN83ulz-nOr-EXNaSCLEcXB7rX6WNwFSOdIBmilN8STYmECA2-zXuk8o42GCk6SXRjJOhMsYpCuT/s1600/frame.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGiHjqxS_uSHpESOM5q3u0VAxW8KdC9kgGcK9gtiN7tIDLOHK4blQ_3LuYeFCTehbtuN83ulz-nOr-EXNaSCLEcXB7rX6WNwFSOdIBmilN8STYmECA2-zXuk8o42GCk6SXRjJOhMsYpCuT/s400/frame.png" width="400" /></a></div>
<br />
<a href="https://ru.aliexpress.com/store/product/Original-DOIT-Metal-Panel-Frame-for-4wd-Car-Tank-Chassis-DIY-RC-Toy-Robot-Vehicle-for/1912455_32776882123.html" target="_blank">https://ru.aliexpress.com/store/product/Original-DOIT-Metal-Panel-Frame-for-4wd-Car-Tank-Chassis-DIY-RC-Toy-Robot-Vehicle-for/1912455_32776882123.html</a><br />
<br />
Материал: алюминий.<br />
Толщина: 3 мм.<br />
Ширина: 15 см.<br />
Длина: 20 см.<br />
<br />
В моей платформе используется две такие пластины.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIapzsFWKk0GoXmXfmfA773hyphenhyphenwJ9aRQbtynDKHZLnw0zAU7BToFyT7wwYLIKVhSsudTGuzZl9YfWWDYkYjPHVqq7v_3EWCPFZXUQ5RjIjhflPKDTAfNVGt07TyNitLohtyFhc55j0BXQwS/s1600/37mm-DC-Gear-Motor-Bracket.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIapzsFWKk0GoXmXfmfA773hyphenhyphenwJ9aRQbtynDKHZLnw0zAU7BToFyT7wwYLIKVhSsudTGuzZl9YfWWDYkYjPHVqq7v_3EWCPFZXUQ5RjIjhflPKDTAfNVGt07TyNitLohtyFhc55j0BXQwS/s400/37mm-DC-Gear-Motor-Bracket.jpg" width="400" /></a></div>
<br />
<a href="https://ru.aliexpress.com/item/37/32674292295.html" target="_blank">https://ru.aliexpress.com/item/37/32674292295.html</a><br />
<br />
Кронштейны для крепления моторов. По ссылке лот включающий четыре кронштейна.<br />
<br />
Эти кронштейны сделаны из алюминия. Они предназначены для моторов 37 мм.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0NDDSGoVhze0EUONAimrpww9eUqAvQcqan58n7KTeIf2Tv54NQj4zg8fXNkOEbGbuSJToW5q9m9qQzvOaB1-G502bn2d3e5KcV03vr5b10lcvxuWUTjm68gqAFZeekpm7tZOCWElp9qsA/s1600/motor_wheel_mount.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0NDDSGoVhze0EUONAimrpww9eUqAvQcqan58n7KTeIf2Tv54NQj4zg8fXNkOEbGbuSJToW5q9m9qQzvOaB1-G502bn2d3e5KcV03vr5b10lcvxuWUTjm68gqAFZeekpm7tZOCWElp9qsA/s400/motor_wheel_mount.png" width="400" /></a></div>
<br />
<a href="https://ru.aliexpress.com/store/product/Original-YDS-4pcs-lot-Hex-coupling-coupler-Hexagon-connector-copper-length30mm-6-mm-5mm-4-mm/1471380_32739794496.html" target="_blank">https://ru.aliexpress.com/store/product/Original-YDS-4pcs-lot-Hex-coupling-coupler-Hexagon-connector-copper-length30mm-6-mm-5mm-4-mm/1471380_32739794496.html</a><br />
<br />
Переходники для крепления колес. По этой ссылке также лот включающий четыре переходника.<br />
<br />
Длина переходников составляет 30 мм. Предназначены для колес с креплением шестигранник 12 мм. Для моих моторов нужны переходники под вал диаметром 6 мм.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR9oBtClOqt4PIuIslwuY0JAfQzLpgm0GJVuAcXuj43xX_bY1jBQ5PtruQee9NJMR4Ue47kxD4niMi6edO020omoMwnewdYS0HcH-I_Rnm7A1a3D24X6JfxZTFVATeaGfLiqb0qoS3kDDB/s1600/wheel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR9oBtClOqt4PIuIslwuY0JAfQzLpgm0GJVuAcXuj43xX_bY1jBQ5PtruQee9NJMR4Ue47kxD4niMi6edO020omoMwnewdYS0HcH-I_Rnm7A1a3D24X6JfxZTFVATeaGfLiqb0qoS3kDDB/s400/wheel.jpg" width="400" /></a></div>
<br />
<a href="https://ru.aliexpress.com/store/product/4-4wd-85/1471380_32672437100.html" target="_blank">https://ru.aliexpress.com/store/product/4-4wd-85/1471380_32672437100.html</a><br />
<br />
Колеса. Лот включает четыре штуки.<br />
<br />
Диаметр колес 85 мм. Крепление - шестигранник 12 мм. Это стандарт для колес радиоуправляемых моделей масштаба 1/10.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh11353f6dD6RlxsA8u2sXQT-FPcOvyXI5AqSDIWfTDbTLTsBZFGbsPjbOs2GtcP1EX2Nmk4NI8FzXNDJwgRfDu43rxDFw0saKSsxBtzHmHQT6oW0lUpTxCDFGaxVzMJXfyL1bORypfmV2g/s1600/motor.jpg" imageanchor="1"><img border="0" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh11353f6dD6RlxsA8u2sXQT-FPcOvyXI5AqSDIWfTDbTLTsBZFGbsPjbOs2GtcP1EX2Nmk4NI8FzXNDJwgRfDu43rxDFw0saKSsxBtzHmHQT6oW0lUpTxCDFGaxVzMJXfyL1bORypfmV2g/s320/motor.jpg" width="400" /></a></div>
<br />
<a href="https://ru.aliexpress.com/item/JGB37-520B-With-encoder-Gear-motor-DC-gear-motor-Encoder-speed-with-encoder-A-B-phase/32698299894.html" target="_blank">https://ru.aliexpress.com/item/JGB37-520B-With-encoder-Gear-motor-DC-gear-motor-Encoder-speed-with-encoder-A-B-phase/32698299894.html</a><br />
<br />
Мотор с энкодером и редуктором. В платформе используется четыре таких.<br />
<br />
Напряжение: 12 вольт<br />
Диаметр выходного вала: 6 мм<br />
Обороты выходного вала: 111 оборотов в минуту<br />
<br />
У этого продавца можно купить двигатели с другой частотой вращения выходного вала.<br />
<br />
Теперь можно подсчитать стоимость платформы.<br />
<br />
Основа платформы.<br />
Цена: US $9.59<br />
Доставка China Post Registered Air Mail: бесплатно<br />
<br />
Кронштейны для крепления моторов.<br />
Цена: US $4.42<br />
Доставка China Post Registered Air Mail: бесплатно<br />
<br />
Переходники для крепления колес.<br />
Цена: US $3.42<br />
Доставка China Post Registered Air Mail: US $3.58<br />
<br />
Колеса.<br />
Цена: US $15.89<br />
Доставка China Post Registered Air Mail: бесплатно<br />
<br />
Мотор с энкодером и редуктором.<br />
Цена: US $12.00<br />
Доставка China Post Registered Air Mail: бесплатно<br />
<br />
Всего получается US $94.49<br />
<br />
Здесь не учтена стоимость крепежа. Винтики, гаечки, шайбы и прочее. Я их покупал в ближайшем магазине, поэтому цену решил не указывать. Но приблизительный перечень необходимого крепежа думаю нужно привести.<br />
<br />
Кронштейны моторов крепятся к основе шестнадцатью винтиками М4х10 мм с цилиндрической головкой. Для них нужно шестнадцать гаечек. Я ещё использовал шестнадцать широких шайб и шестнадцать шайб гровера.<br />
<br />
Моторы крепятся к кронштейнам двадцатью четырьмя винтиками М3х8 мм с потайной головкой. Винтики длиннее 8 мм использовать нельзя.<br />
<br />
Для крепления переходников колес к валу моторов можно использовать четыре винтика М3х8 мм.<br />
<br />
Колеса крепятся четырьмя винтиками М4х10 мм с цилиндрической головкой. Я ещё использовал четыре узкие шайбы и четыре шайбы гровера.<br />
<br />
Основные пластины крепятся друг к другу восемью винтами М4х80 мм. К ним нужно 32 гаечки. У меня ещё использованы 32 широкие шайбы и 8 шайб гровера. Лучше конечно добавить ещё 8 шайб гровера. Но я думаю верхнюю пластину нужно будет иногда снимать для установки разных сенсоров и прочего. Без шайб гровера это делать проще. Так оно или нет станет ясно в процессе эксплуатации.<br />
<br />
Фото получившейся платформы.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_vRS2jqyV4u3VlLRmVk2pGXSA4BOI_ZRqU3ercD6p9cb4pSAdFBzrZAigZwrlGNuHc42c4SIpNsqq7tk_MJTKDRSkDV0GQa1Ob028H23cXrLW3TKr7fZdNYRLb9ESreE-uQj7HvI1y_1Z/s1600/IMG_0265.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_vRS2jqyV4u3VlLRmVk2pGXSA4BOI_ZRqU3ercD6p9cb4pSAdFBzrZAigZwrlGNuHc42c4SIpNsqq7tk_MJTKDRSkDV0GQa1Ob028H23cXrLW3TKr7fZdNYRLb9ESreE-uQj7HvI1y_1Z/s400/IMG_0265.JPG" width="400" /></a></div>
<br />
Вид сверху.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNJPJOpdKSqU81Fpr93KfvjCDoDTbqdcl1w2bhzW08uCiV_un6tzoRM6dwObrxNnLTpqyZVnmKUaK0ZGKj3PBSWNbEsJL4t_nmxqvXUBP6TryCNJOAACa64sl9gt7d127AVd-c1cj8jlH/s1600/IMG_0266.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNJPJOpdKSqU81Fpr93KfvjCDoDTbqdcl1w2bhzW08uCiV_un6tzoRM6dwObrxNnLTpqyZVnmKUaK0ZGKj3PBSWNbEsJL4t_nmxqvXUBP6TryCNJOAACa64sl9gt7d127AVd-c1cj8jlH/s400/IMG_0266.JPG" width="400" /></a></div>
<br />
Вид сбоку.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3CT4mH6D1x1H_cngQAcwya2cg-L8DiDsjvGBA2eRUGBRN-i5S1WkP3lVG6wtIVhIfUNIWNZJrwsucUdOV7qTmDNEL4q7eVi8fnlaISWyYj8kQqogDRvzlAK7C4VkvhzbRWMd8yNtt-JIi/s1600/IMG_0245.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3CT4mH6D1x1H_cngQAcwya2cg-L8DiDsjvGBA2eRUGBRN-i5S1WkP3lVG6wtIVhIfUNIWNZJrwsucUdOV7qTmDNEL4q7eVi8fnlaISWyYj8kQqogDRvzlAK7C4VkvhzbRWMd8yNtt-JIi/s400/IMG_0245.JPG" width="400" /></a></div>
<br />
Вид спереди.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-gHhNM79vF2CztcuOHnFhyXc_RS_yeeX7oRiSsz6907w0Z2e9-AV4qhO5pSIk5QJMrPCBojnbWU09Ep3QSCt74sDrNEZMKrWagFeeclj8h5TQSQNhul8yCDwdrKLvrgFSzsGMS323NmMC/s1600/IMG_0242.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-gHhNM79vF2CztcuOHnFhyXc_RS_yeeX7oRiSsz6907w0Z2e9-AV4qhO5pSIk5QJMrPCBojnbWU09Ep3QSCt74sDrNEZMKrWagFeeclj8h5TQSQNhul8yCDwdrKLvrgFSzsGMS323NmMC/s400/IMG_0242.JPG" width="400" /></a></div>
<br />
Вид сзади.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-Fq1PqweLkT2TlWQV7meBk0XIvcKWyTc3jRicXzKE3SLdZHWuBc-f9l6OzUp8NBIDFXfg6mSNQk8QpVqBpBairL9KfnVe6QbjsZK1_JHtVVY8exVBOoOEJOfV1WIZd93Oq0CAyv5bodip/s1600/IMG_0256.JPG" imageanchor="1"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-Fq1PqweLkT2TlWQV7meBk0XIvcKWyTc3jRicXzKE3SLdZHWuBc-f9l6OzUp8NBIDFXfg6mSNQk8QpVqBpBairL9KfnVe6QbjsZK1_JHtVVY8exVBOoOEJOfV1WIZd93Oq0CAyv5bodip/s320/IMG_0256.JPG" width="400" /></a></div>
<br />
Вид снизу.<br />
<br />
Характеристики платформы.<br />
<br />
Длина: 20 см.<br />
Ширина: 25 см.<br />
Высота: 8.5 см.<br />
Дорожный просвет: 2 см.<br />
Максимальная скорость: 49.4 см/с (расчетная).<br />
<br />
Теперь, полагаю, нужно подвести некоторый итог.<br />
<br />
В общем, получившаяся платформа мне нравится. Двигатели 37 мм потребляют меньше тока, чем двигатели 25 мм (по данным продавцов). Все двигатели оснащены энкодерами. Редукторы с металлическими шестеренками. Энкодеры, разъемы, провода защищены нижней пластиной. Она же должна облегчить отладку кода (проще колеса вывесить). Резина колес должна способствовать снижению вибраций. Платформа 4WD.<br />
<br />
Что не нравится. Платформа получилась массивная. Заметна деформация резины. Небольшой дорожный просвет. Для платформы подходят колеса диаметром менее 95 мм. Самые большие из подходящих, найденные мной, имеют диаметр 85 мм. Вообще, купленные колеса мне не нравятся.<br />
<br />
Платформа стоит около US $100. Вроде не много, но и не мало.<br />
<br />
Эксплуатация покажет насколько хороша/плоха получившаяся робоплатформа.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-71206882532035873152016-09-02T14:27:00.000-07:002016-09-02T15:18:30.977-07:00Робот с ультразвуковым дальномером<div dir="ltr" style="text-align: left;" trbidi="on">
В статье рассказывается о простой платформе с ультразвуковым дальномером HC-SR04. Приводится скетч управляющий роботом. С этим кодом робот просто старается избегать столкновений с препятствиями.<br />
<br />
<a name='more'></a><br />
В полностью собранном виде робот выглядит так:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7TJWa7FxnCwUCh4a_5JWJ8C8Xja88SkUyYydfeBTfE9xOQFnomSy3R0IyghSvbQAImt3efrPPcRzx6qCu5hd2YgKZtYxa4KWwsMKO4wsieByYwruDaEgMpikzwQ2SpQEzDvj3a5RcSQt4/s1600/robot.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7TJWa7FxnCwUCh4a_5JWJ8C8Xja88SkUyYydfeBTfE9xOQFnomSy3R0IyghSvbQAImt3efrPPcRzx6qCu5hd2YgKZtYxa4KWwsMKO4wsieByYwruDaEgMpikzwQ2SpQEzDvj3a5RcSQt4/s400/robot.JPG" width="400" /></a></div>
<br />
Обычная трехколесная тележка. Моторы коллекторные с редукторами. В ранее опубликованных статьях есть детальные фотографии и подробное описание.<br />
<br />
Мозгом робота является Arduino Uno.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjgww0PPgRvJNmmWfI_7iwtHWas9ganA8qs6vz5dBmGVrF3ZJ2CRhKbLBhoDdzwyfeMGQQV_qqxk9mmAvuFkhTGJ08w1YMBmmbOSyAY7o9HhIM_-fu-UDNW-8NZ4HZ6EWlrQEh_q_BCf2f/s1600/arduino_uno.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjgww0PPgRvJNmmWfI_7iwtHWas9ganA8qs6vz5dBmGVrF3ZJ2CRhKbLBhoDdzwyfeMGQQV_qqxk9mmAvuFkhTGJ08w1YMBmmbOSyAY7o9HhIM_-fu-UDNW-8NZ4HZ6EWlrQEh_q_BCf2f/s400/arduino_uno.jpg" width="400" /></a></div>
<br />
Подключается все к ардуино через Sensor Shield V4.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZok08-R2pkW6j0Ay49VLr55Doz6dOBHfhxeX0G4tAiRA4FzhMhgH6onrb8cgY46v47ZnVC8nMP37UkG_zOh2aQn2yF676YYO8B422SEkJpDL6zoE6C20wZEVyTXaXGxUX-dDK6EV2r_UL/s1600/sensor_shield_4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZok08-R2pkW6j0Ay49VLr55Doz6dOBHfhxeX0G4tAiRA4FzhMhgH6onrb8cgY46v47ZnVC8nMP37UkG_zOh2aQn2yF676YYO8B422SEkJpDL6zoE6C20wZEVyTXaXGxUX-dDK6EV2r_UL/s400/sensor_shield_4.jpg" width="400" /></a></div>
<br />
Данные об окружающей среде робот получает от ультразвукового сенсора HC-SR04.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2E64Os6IiYx6NDOfwBQ_3Qyiy1UTIZTngKWBbOsFXgsQRTAcvCMGLuQVqdscrNGdDQ2nySi9hO7R9ib54vNn-RuVRA-DbweIKGFMO8TVAk0vQV7eur8Qs-JQl9TDWA-DMpkz_gv28nOOr/s1600/hc-sr04.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2E64Os6IiYx6NDOfwBQ_3Qyiy1UTIZTngKWBbOsFXgsQRTAcvCMGLuQVqdscrNGdDQ2nySi9hO7R9ib54vNn-RuVRA-DbweIKGFMO8TVAk0vQV7eur8Qs-JQl9TDWA-DMpkz_gv28nOOr/s400/hc-sr04.jpg" width="400" /></a></div>
<br />
Драйвер двигателей на L9110S.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCT3DCnp3iy8rgJDf4BcH0B188159ISc_kJ1QHdEO5FqTt6oHqNb-pSl0S35f5MATtos_h7Ozn7A_Pprw636_TGCJ8WNdPLnXhE4_DoktPmVl8klw45bSBS_Nm4BQhgsjdnrw-8OpTGoEv/s1600/l9110s.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCT3DCnp3iy8rgJDf4BcH0B188159ISc_kJ1QHdEO5FqTt6oHqNb-pSl0S35f5MATtos_h7Ozn7A_Pprw636_TGCJ8WNdPLnXhE4_DoktPmVl8klw45bSBS_Nm4BQhgsjdnrw-8OpTGoEv/s400/l9110s.jpg" width="400" /></a></div>
<br />
Левый двигатель подключаются к клеммам драйвера MOTOR A. Правый двигатель подключается к клеммам драйвера MOTOR B.<br />
<br />
Между собой электронные компоненты соединяются согласно ниже изложенным рекомендациям.<br />
<br />
Arduino --- Ultrasonic Sensor HC-SR04<br />
GND --- GND<br />
VCC --- VCC<br />
D4 --- Trig<br />
D5 --- Echo<br />
<br />
Arduino --- Motor Driver L9110S<br />
GND --- GND<br />
VCC --- VCC<br />
D13 --- A-IA<br />
D12 --- A-IB<br />
D11 --- B-IA<br />
D10 --- B-IB<br />
<br />
Более подробно о работе с коллекторными двигателями и их драйверами я писал в <a href="http://justforduino.blogspot.ru/2015/02/blog-post.html" target="_blank">http://justforduino.blogspot.ru/2015/02/blog-post.html</a><br />
<br />
Скетч:<br />
<br />
<pre>////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Sketch: Robot
//
#include <util/delay.h>
const unsigned char A_IA = 13;
const unsigned char A_IB = 12;
const unsigned char B_IA = 11;
const unsigned char B_IB = 10;
const unsigned char TRIG = 4;
const unsigned char ECHO = 5;
unsigned int data = 0;
unsigned long int time1 = 0;
unsigned long int time2 = 0;
void forward_forward( void )
{
digitalWrite(A_IA, HIGH);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, HIGH);
digitalWrite(B_IB, LOW);
}
void backward_backward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, HIGH);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, HIGH);
}
void forward_stop( void )
{
digitalWrite(A_IA, HIGH);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, LOW);
}
void backward_stop( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, HIGH);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, LOW);
}
void stop_forward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, HIGH);
digitalWrite(B_IB, LOW);
}
void stop_backward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, HIGH);
}
void forward_backward( void )
{
digitalWrite(A_IA, HIGH);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, HIGH);
}
void backward_forward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, HIGH);
digitalWrite(B_IA, HIGH);
digitalWrite(B_IB, LOW);
}
void stop_stop( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, LOW);
}
void setup()
{
pinMode(A_IA, OUTPUT);
pinMode(A_IB, OUTPUT);
pinMode(B_IA, OUTPUT);
pinMode(B_IB, OUTPUT);
stop_stop();
pinMode(TRIG, OUTPUT);
digitalWrite(TRIG, LOW);
pinMode(ECHO, INPUT);
_delay_ms(4000);
}
void loop()
{
digitalWrite(TRIG, HIGH);
_delay_us(10);
digitalWrite(TRIG, LOW);
while( digitalRead(ECHO) == LOW ) ;
time1 = micros();
while( digitalRead(ECHO) == HIGH ) ;
time2 = micros();
// data = ((((time2 - time1) / 2.0) / 1000000.0) * 350) * 100;
data = (time2 - time1) * 0.0175;
if ( data < 45 ) forward_backward();
if ( data > 55 ) forward_forward();
}
//
// End
//
////////////////////////</pre>
<br />
В показанной программе реализованы все возможные направления движения платформы. Хотя реально используется только три функции управляющие моторами.<br />
<br />
Есть в коде пара интересных строк:<br />
<br />
if ( data < 45 ) forward_backward();<br />
if ( data > 55 ) forward_forward();<br />
<br />
Можно было написать так:<br />
<br />
if ( data < 45 ) forward_backward();<br />
else forward_forward();<br />
<br />
Но в этом случае робот оказавшись перед препятствием стал бы слишком часто вызывать функции forward_backward и forward_forward.<br />
<br />
Видео:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/kZAjQ8KDOdo/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/kZAjQ8KDOdo?feature=player_embedded" width="320"></iframe></div>
<br />
Очевидно эта платформа плохо подходит для улицы. Едет так криво, что дальше некуда.<br />
<br />
Одного ультразвукового сенсора явно недостаточно. Для надежного избегания столкновений с препятствиями стоит добавить инфракрасный датчик препятствий. И контактные датчики не будут лишними.<br />
<br />
Из серьезных недостатков следует отметить питание двигателей. Оно реализовано через линейный стабилизатор ардуино. Стабилизатор очень сильно греется. Что не удивительно.<br />
<br />
Питание двигателей лучше организовать через импульсный понижающий преобразователь.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-57540853604553456672016-08-23T14:45:00.000-07:002016-08-23T14:55:10.070-07:00Ультразвуковой дальномер<div dir="ltr" style="text-align: left;" trbidi="on">
Небольшая статья о HC-SR04. Подключение к ардуино, скетч, описание особенностей работы дальномера.<br />
<br />
<a name='more'></a><br />
Для начала покажу сам ультразвуковой модуль<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibL0IscywvHo2INczy9NKpYOrHkmPV_QlwKnqP3tNGLmXvF4IqFgbtT8CljHJPtkTu9kKaZWBcVoI-qSVLOpnCVG6TJ_DFPJfUSJkzOGSbXeQiisMndyji4zhYr5qcnrK4tp42Awwny0Nt/s1600/ultrasonic.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibL0IscywvHo2INczy9NKpYOrHkmPV_QlwKnqP3tNGLmXvF4IqFgbtT8CljHJPtkTu9kKaZWBcVoI-qSVLOpnCVG6TJ_DFPJfUSJkzOGSbXeQiisMndyji4zhYr5qcnrK4tp42Awwny0Nt/s320/ultrasonic.jpg" width="320" /></a></div>
<br />
Модуль пяти вольтовый. Для запуска процесса измерения расстояния необходимо на ножке Trig установить логическую единицу на 10 микросекунд. Тогда ультразвуковой модуль установит логическую единицу на ножке Echo. Логическая единица будет на этой ножке столько, сколько потребуется звуку на прохождение пути до препятствия и обратно, но не более 38 миллисекунд.<br />
<br />
К ардуино модуль подключается просто<br />
<br />
Arduino --- HC-SR04<br />
GND --- GND<br />
5V --- VCC<br />
D4 --- Trig<br />
D5 --- Echo<br />
<br />
Скетч<br />
<br />
<pre>////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Sketch: HC-SR04
//
#include <util/delay.h>
const unsigned char TRIG = 4;
const unsigned char ECHO = 5;
unsigned int data = 0;
unsigned long int time1 = 0;
unsigned long int time2 = 0;
void setup()
{
pinMode(TRIG, OUTPUT);
digitalWrite(TRIG, LOW);
pinMode(ECHO, INPUT);
Serial.begin(9600);
}
void loop()
{
_delay_ms(1000);
digitalWrite(TRIG, HIGH);
_delay_us(10);
digitalWrite(TRIG, LOW);
while( digitalRead(ECHO) == LOW ) ;
time1 = micros();
while( digitalRead(ECHO) == HIGH ) ;
time2 = micros();
// data = ((((time2 - time1) / 2.0) / 1000000.0) * 350.0) * 100.0;
data = (time2 - time1) * 0.0175;
Serial.println(data);
}
//
// End
//
////////////////////////</pre>
<br />
Скетч с интервалом в секунду передает измеренное расстояние через UART. Посмотреть результаты измерений можно в стандартном мониторе порта Arduino IDE (Сервис - Монитор порта).<br />
<br />
Скажу несколько слов об особенностях программы на которые стоит обратить внимание. Конструкции типа while( digitalRead(ECHO) == LOW ) ; и while( digitalRead(ECHO) == HIGH ) ; не стоит применять в ответственных проектах. Это связано с тем, что в этих конструкциях программа может зациклится навсегда. В серьёзных проектах необходимо предусматривать альтернативную возможность завершения работы таких циклов. Можно использовать сторожевой таймер.<br />
<br />
Расстояние с этой программой измеряется не очень точно. Причина в непостоянстве скорости звука. Она зависит от состава воздуха, температуры, давления и пр. В моем скетче скорость звука установлена в 350 м/с. Эта цифра получена опытным путем. Так как высокая точность в данном проекте не требуется, то калибровка прибора в программе не предусмотрена.<br />
<br />
Очень полезно поиграть с этим дальномером перед использованием его в своих проектах. Стоит померить расстояние до предметов различной формы, с различным типом поверхности, под разными углами.<br />
<br />
Расстояние до ковров и котов измерить этим устройством проблематично. Правда коты бывают разной степени мохнатости, впрочем, как и ковры.<br />
<br />
Расстояние к плоскому и гладкому предмету под острым углом замерить также непросто. Угол отражения равен углу падения. Отраженный предметом звук не попадает в приемник.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-16807654851307143452016-08-20T11:34:00.000-07:002016-08-20T11:34:53.500-07:00Очень полезный скетч<div dir="ltr" style="text-align: left;" trbidi="on">
Здесь я обычно привожу краткое описание содержания статьи. На этот раз решил сохранить интригу :)<br />
<br />
<a name='more'></a><br />
Скетч:<br />
<br />
<pre>////////////////////////
//
// Arduino UNO
//
////////////////////////
//
// Sketch:
//
void setup()
{
DDRB = 0b00000000;
PORTB = 0b00000000;
DDRC = 0b00000000;
PORTC = 0b00000000;
DDRD = 0b00000000;
PORTD = 0b00000000;
}
void loop()
{
}
//
// End
//
////////////////////////</pre>
<br />
Скетч предназначен для платок с микроконтроллерами ATmega328 и ATmega168.<br />
<br />
Рекомендуется загружать этот скетч в ардуино перед сборкой нового устройства. Программа настраивает все ножки контроллера как вход без подтяжки. Такая конфигурация обеспечивает достаточную защиту микроконтроллера и подключаемых модулей.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-6151593976082261352016-04-19T09:18:00.001-07:002016-04-19T09:24:28.817-07:00Книги<div dir="ltr" style="text-align: left;" trbidi="on">
В своих статьях я крайне мало комментирую код. Это не очень правильно. В будущем постараюсь исправить этот недостаток. А сейчас хочу рассказать о паре книг, которые помогут разобраться в любой программе для ардуино.<br />
<br />
<a name='more'></a><br />
Шпак Ю. А. Программирование на языке C для AVR и PIC микроконтроллеров.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpmDRPhbduXHqj3SaY9s0F5pjY4KocN6vfLv0o3sP3ktj5vlPiHSYvZvVo4i0Xg26Gso9witmFYIp2xaNJXv8nqbnLaGl7apYe2nW7h45vhdDJHKL8XWWsauI_TfuBt1o4qRS1hD_9MlEe/s1600/1008767693.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpmDRPhbduXHqj3SaY9s0F5pjY4KocN6vfLv0o3sP3ktj5vlPiHSYvZvVo4i0Xg26Gso9witmFYIp2xaNJXv8nqbnLaGl7apYe2nW7h45vhdDJHKL8XWWsauI_TfuBt1o4qRS1hD_9MlEe/s400/1008767693.jpg" width="287" /></a></div>
<br />
Информация содержащаяся в этой книге будет очень полезна при написании скетчей в Arduino IDE. Полученные знания позволят писать программы на Си в Atmel Studio. После ознакомления с этой книгой читать код станет значительно легче.<br />
<br />
Ревич Ю. В. Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXybI5jQXy3CZRL5INlPeztcnTmkMsvbaSbAAy14kYyZ0khTabgcKg_GlKpHXEftgXNs67LMPAthyphenhyphenvhplw5dYGTpEpeniDoNnYb4KROeaj2ePeH3FarRv1tJYqMVdQZ6Qv7VEqqUhpnS-T/s1600/1010258875.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXybI5jQXy3CZRL5INlPeztcnTmkMsvbaSbAAy14kYyZ0khTabgcKg_GlKpHXEftgXNs67LMPAthyphenhyphenvhplw5dYGTpEpeniDoNnYb4KROeaj2ePeH3FarRv1tJYqMVdQZ6Qv7VEqqUhpnS-T/s400/1010258875.jpg" width="282" /></a></div>
<br />
После прочтения книги Вы сможете писать программы на ассемблере в Atmel Studio. Знания полученные из этой книги пригодятся при написании ассемблерных вставок. Изучив эту книгу Вы сможете работать с дизассемблером. При возникновении необходимости это позволит более глубоко проанализировать работу программы. Ознакомление с ассемблером поможет лучше понять, как работает микроконтроллер.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-45824294365509990692016-04-15T11:13:00.000-07:002016-04-15T11:25:11.438-07:00Обучение управлению RC самолетом<div dir="ltr" style="text-align: left;" trbidi="on">
Продолжение предыдущей статьи. Здесь представлена новая программа и рассказано об основных отличиях этой программы от кода показанного в ранее опубликованной статье.<br />
<br />
<a name='more'></a><br />
Сначала напомню основные моменты. Предлагаемое устройство должно способствовать облегчению процесса обучения управлению радиоуправляемым самолетом. Само устройство состоит из Arduino Pro Mini ATmega328P (5V, 16MHz). К ардуино подключаются два приемника (учителя и ученика) и электроника самолета (ESC и сервоприводы). Подробное описание соединения компонентов представлено ниже.<br />
<br />
Подключение приемника от аппаратуры учителя к ардуино<br />
<br />
Arduino --- Receiver<br />
D0 --- CH1 (AIL)<br />
D1 --- CH2 (ELE)<br />
D2 --- CH5 (тумблер)<br />
D3 --- CH3 (THR)<br />
D4 --- CH4 (RUD)<br />
VCC --- VCC<br />
GND --- GND<br />
<br />
Подключение приемника от аппаратуры ученика к ардуино<br />
<br />
Arduino --- Receiver<br />
A0 --- CH1 (AIL)<br />
A1 --- CH2 (ELE)<br />
A3 --- CH3 (THR)<br />
A4 --- CH4 (RUD)<br />
VCC --- VCC<br />
GND --- GND<br />
<br />
Подключение электроники самолета к ардуино<br />
<br />
Arduino --- Airplane<br />
D8 --- AIL (сервоприводы элеронов)<br />
D9 --- ELE (сервопривод руля высоты)<br />
D11 --- THR (регулятор электродвигателя)<br />
D12 --- RUD (сервопривод руля направления)<br />
<br />
Земля всех компонентов соединяется с землей ардуино. Питание всех компонентов также соединяется с питанием ардуино.<br />
<br />
Выше приведен один из возможных вариантов подключения электронных компонентов самолета к ардуино. Всё зависит от конструкции конкретного самолета.<br />
<br />
Программа<br />
<br />
<pre>;---------------------------------------------
; Program : Trainer
; Compiler : Atmel Studio
; Chip type : ATmega328P
; System Clock : 16 MHz
; Date :
;---------------------------------------------
.include "m328Pdef.inc"
;---------------------------------------------
; Interrupt vectors
.cseg
.org 0x0000 ; Reset
jmp RESET
.org 0x0002 ; External Interrupt Request 0
reti
.org 0x0004 ; External Interrupt Request 1
reti
.org 0x0006 ; Pin Change Interrupt Request 0
reti
.org 0x0008 ; Pin Change Interrupt Request 1
reti
.org 0x000A ; Pin Change Interrupt Request 2
reti
.org 0x000C ; Watchdog Time-out Interrupt
reti
.org 0x000E ; Timer/Counter 2 Compare Match A
reti
.org 0x0010 ; Timer/Counter 2 Compare Match B
reti
.org 0x0012 ; Timer/Counter 2 Overflow
reti
.org 0x0014 ; Timer/Counter 1 Capture Event
reti
.org 0x0016 ; Timer/Counter 1 Compare Match A
reti
.org 0x0018 ; Timer/Counter 1 Compare Match B
reti
.org 0x001A ; Timer/Counter 1 Overflow
reti
.org 0x001C ; Timer/Counter 0 Compare Match A
reti
.org 0x001E ; Timer/Counter 0 Compare Match B
reti
.org 0x0020 ; Timer/Counter 0 Overflow
reti
.org 0x0022 ; SPI Serial Transfer Complete
reti
.org 0x0024 ; USART, Rx Complete
reti
.org 0x0026 ; USART, UDR Empty
reti
.org 0x0028 ; USART, Tx Complete
reti
.org 0x002A ; ADC Conversion Complete
reti
.org 0x002C ; EEPROM Ready
reti
.org 0x002E ; Analog Comparator
reti
.org 0x0030 ; Two-wire Serial Interface
reti
.org 0x0032 ; Store Program Memory Read
reti
.org INT_VECTORS_SIZE
;---------------------------------------------
RESET:
;---------------------------------------------
; Steck initialization
ldi R16, Low(RAMEND)
out SPL, R16
ldi R16, High(RAMEND)
out SPH, R16
;---------------------------------------------
; USART
ldi R16, 0
sts UBRR0H, R16
sts UBRR0L, R16
sts UCSR0A, R16
sts UCSR0B, R16
sts UCSR0C, R16
;---------------------------------------------
; Input/Output ports
ldi R16, 0b00000000
out PORTB, R16
ldi R16, 0b00111111
out DDRB, R16
ldi R16, 0b00000000
out PORTC, R16
ldi R16, 0b00000000
out DDRC, R16
ldi R16, 0b00000000
out PORTD, R16
ldi R16, 0b00000000
out DDRD, R16
;---------------------------------------------
; Timer/Counter 2
ldi R16, 0
sts TCNT2, R16
; COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
ldi R16, 0
sts TCCR2A, R16
; FOC2A FOC2B - - WGM22 CS22 CS21 CS20
ldi R16, ((1<<CS22)|(1<<CS21))
sts TCCR2B, R16
; - - - - - OCIE2B OCIE2A TOIE2
ldi R16, 0
sts TIMSK2, R16
; - - - - - OCF2B OCF2A TOV2
ldi R16, 0
sts TIFR2, R16
;---------------------------------------------
eor R16, R16
eor R17, R17
eor R18, R18
eor R19, R19
eor R20, R20
eor R21, R21
eor R22, R22
;---------------------------------------------
; Global interrupt disable
cli
;---------------------------------------------
; main
main:
cpi R17, 94
brsh l_01 ; R17 >= 94
cpi R18, 1
brne l_02 ; R18 != 1
in R19, PIND
out PORTB, R19
sbic PIND, 2 ; (PIND & 0b00000100) == 0
rjmp l_03
cpi R20, 1
brne main ; R20 != 1
lds R17, TCNT2
ldi R20, 0
rjmp main
l_03:
cpi R20, 0
brne main ; R20 != 0
sts TCNT2, R16
ldi R20, 1
rjmp main
l_02:
cpi R18, 2
brne l_04 ; R18 != 2
in R19, PINC
out PORTB, R19
andi R19, 0b00011011
brne main ; R19 != 0
ldi R18, 0
rcall delay ; delay
rjmp main
l_04:
in R19, PIND
andi R19, 0b00011011
brne main ; R19 != 0
ldi R18, 1
rjmp main
l_01:
cpi R18, 2
brne l_05 ; R18 != 2
in R19, PINC
out PORTB, R19
sbic PIND, 2 ; (PIND & 0b00000100) == 0
rjmp l_06
cpi R20, 1
brne main ; R20 != 1
lds R17, TCNT2
ldi R20, 0
rjmp main
l_06:
cpi R20, 0
brne main ; R20 != 0
sts TCNT2, R16
ldi R20, 1
rjmp main
l_05:
cpi R18, 1
brne l_07 ; R18 != 1
in R19, PIND
out PORTB, R19
andi R19, 0b00011011
brne main ; R19 != 0
ldi R18, 0
rcall delay ; delay
rjmp main
l_07:
in R19, PINC
andi R19, 0b00011011
brne main ; R19 != 0
ldi R18, 2
rjmp main
;---------------------------------------------
; wait 10 ms
delay:
ldi R21, 0x40 ; Low byte
ldi R22, 0x9C ; High byte
l_10:
subi R21, 1
sbci R22, 0
brcc l_10
ret
;---------------------------------------------</pre>
<br />
Программа написана на ассемблере. Как превратить такой код в прошивку я уже рассказывал <a href="http://justforduino.blogspot.ru/2014/10/atmel-studio-6.html" target="_blank">http://justforduino.blogspot.ru/2014/10/atmel-studio-6.html</a> Про загрузку получившейся прошивки в ардуино тоже уже писал <a href="http://justforduino.blogspot.ru/2014/10/arduino.html" target="_blank">http://justforduino.blogspot.ru/2014/10/arduino.html</a><br />
<br />
Достоинством ассемблерной программы является относительная простота расчета времени выполнения кода. Чтобы оценить время выполнения скетча ардуино необходимо дизассемблировать прошивку созданную Arduino IDE. Это несколько сложнее и менее надежно. Возможны ошибки.<br />
<br />
Итак. Программа обновляет порт B (D8, D9, D10, D11, D12, D13) максимум за 17 тактов. Контроллер работает на частоте 16 MHz. Значит за одну микросекунду выполняется 16 тактов. Таким образом программа может изменять длительность управляющих импульсов на плюс минус одну микросекунду (сервоприводы такие колебания не замечают).<br />
<br />
((1.0 / 16000000.0) * 17.0 ) * 1000000.0 = 1.0625 us<br />
<br />
Управляющие импульсы не выходят за допустимые границы и всегда находятся в пределах от 1000 до 2000 микросекунд.<br />
<br />
Между управляющими импульсами должна присутствовать пауза. Её длительность обычно составляет от 18000 до 19000 микросекунд. Не значительные изменения времени паузы никак не проявляются. В представленной программе, в момент переключения управления, возможно изменение длительности паузы от 10000 до 30000 микросекунд. Это ни какого влияния ни на что не оказывает.<br />
<br />
Показанная в этой статье программа сильно лучше скетча из прошлой статьи. Она работает довольно быстро и достаточно точно.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-51431075233572494552016-04-10T20:51:00.000-07:002016-04-15T11:21:22.308-07:00Обучение управлению радиоуправляемым самолетом<div dir="ltr" style="text-align: left;" trbidi="on">
В статье рассказывается об устройстве, которое должно помочь обучению. Разумеется проект реализован на ардуино.<br />
<br />
<a name='more'></a><br />
Сразу скажу, начинать учится летать нужно в симуляторе. Тем более, есть открытые проекты.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmLdH33NKb-DeYJJxNzCyz4W6qi82t5FAQYt5lNGdw-usmlAiMXGkrgtERRwqH-vuVgMmA43mF298LIGoom9fixJNPzeq34kjDMHQU7SQHg02w0os9ubjQlRjJa8T2dgsEaIF6jPbAs0EE/s1600/crrcsim.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmLdH33NKb-DeYJJxNzCyz4W6qi82t5FAQYt5lNGdw-usmlAiMXGkrgtERRwqH-vuVgMmA43mF298LIGoom9fixJNPzeq34kjDMHQU7SQHg02w0os9ubjQlRjJa8T2dgsEaIF6jPbAs0EE/s400/crrcsim.png" width="400" /></a></div>
<br />
Вот только опыт управления реальным самолетом симулятор не заменит. Описываемый проект служит облегчению процесса обучения.<br />
<br />
Устройство состоит из Arduino Pro Mini ATmega328P (5V, 16MHz)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhukNSgng8jJaLyVBxBhtY0J9E0y_06KbA0NYhkzNOVs9l7zmz5c7y5DZrMkkdeJLC8Bqd2pqOsqB7k5zzNHL1aLanbH99uEp7II97lVedZjiK7MuN4boq5zmYKD0q6SeWglu3mdlyDvjYk/s1600/arduino.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="297" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhukNSgng8jJaLyVBxBhtY0J9E0y_06KbA0NYhkzNOVs9l7zmz5c7y5DZrMkkdeJLC8Bqd2pqOsqB7k5zzNHL1aLanbH99uEp7II97lVedZjiK7MuN4boq5zmYKD0q6SeWglu3mdlyDvjYk/s400/arduino.JPG" width="400" /></a></div>
<br />
На самом деле подойдет любая ардуино с контроллером ATmega328 или ATmega168. Просто Arduino Pro Mini самая маленькая и легкая. Конечно лучше сделать специальную платку, но для начала и Pro Mini сгодится.<br />
<br />
К ардуино подключаются приемник от аппаратуры учителя, приемник от аппаратуры ученика, регулятор и сервоприводы самолета. Кто именно управляет самолетом зависит от положения тумблера на аппаратуре учителя. Думаю уже ясно, что аппаратура учителя и соответствующий ей приемник должны иметь минимум 5 каналов. Аппаратура ученика и его приемник могут быть и 4 канальными.<br />
<br />
Скетч<br />
<br />
<pre>////////////////////////
//
// Arduino
//
////////////////////////
//
// Sketch: Trainer
//
// Arduino Receiver 1
//
// D0 --- CH1 (AIL)
// D1 --- CH2 (ELE)
// D2 --- CH5
// D3 --- CH3 (THR)
// D4 --- CH4 (RUD)
// Arduino Receiver 2
//
// A0 --- CH1 (AIL)
// A1 --- CH2 (ELE)
// A3 --- CH3 (THR)
// A4 --- CH4 (RUD)
// Arduino Airplane
//
// D8 --- AIL (CH1)
// D9 --- ELE (CH2)
// D11 --- THR (CH3)
// D12 --- RUD (CH4)
volatile unsigned char time = 0;
void setup()
{
// Global disable interrupts
cli();
// Port B initialization
// - - PB5 PB4 PB3 PB2 PB1 PB0
DDRB = 0b00111111;
PORTB = 0b00000000;
// Port C initialization
// - - PC5 PC4 PC3 PC2 PC1 PC0
DDRC = 0b00000000;
PORTC = 0b00000000;
// Port D initialization
// PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
DDRD = 0b00000000;
PORTD = 0b00000000;
// External Interrupt initialization
// – – – – ISC11 ISC10 ISC01 ISC00
EICRA = (1<<ISC00);
// – – – – – – INT1 INT0
EIMSK = (1<<INT0);
// – – – – – – INTF1 INTF0
EIFR = (1<<INTF0);
// Timer/Counter 0 initialization
TCNT0 = 0;
// COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00
TCCR0A = 0;
// FOC0A FOC0B - - WGM02 CS02 CS01 CS00
TCCR0B = 0;
// - - - - - OCIE0B OCIE0A TOIE0
TIMSK0 = 0;
// - - - - - OCF0B OCF0A TOV0
TIFR0 = 0;
// Timer/Counter 2 initialization
TCNT2 = 0;
// COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
TCCR2A = 0;
// FOC2A FOC2B - - WGM22 CS22 CS21 CS20
TCCR2B = ((1<<CS22)|(1<<CS21));
// - - - - - OCIE2B OCIE2A TOIE2
TIMSK2 = 0;
// - - - - - OCF2B OCF2A TOV2
TIFR2 = 0;
// Global enable interrupts
sei();
}
void loop()
{
while (1)
{
if ( time < 94 )
{
PORTB = PIND;
}
else
{
PORTB = PINC;
}
}
}
ISR(INT0_vect)
{
if ( (PIND & (1<<2)) == 0 )
{
time = TCNT2;
}
else
{
TCNT2 = 0;
}
}
//
// End
//
////////////////////////</pre>
<br />
Соединение компонентов описано в начале программы. Сама программа очень простая. Обработчик прерывания по внешнему сигналу INT0 измеряет длительность управляющего импульса на 5 канале приемника учителя. Если сигнал меньше 1500 микросекунд, то на выход передаются сигналы с аппаратуры учителя. Если сигнал больше 1500 микросекунд, то на выход передаются сигналы с аппаратуры ученика и управление самолетом переходит в его руки.<br />
<br />
В заключении несколько важных замечаний. Это устройство предназначено для работы с приемниками выдающими управляющие сигналы длительностью от 1000 до 2000 микросекунд с частотой в 50 герц.<br />
<br />
Возможно потребуется внешний BEC, так как тока выдаваемого стабилизатором ESC может не хватить на два приемника, ардуино и сервоприводы.<br />
<br />
В реальных условиях устройство не проверялось. Был собран небольшой тестовый стендик. К выходам ардуино подключались сервоприводы HEXTRONIK HXT900. А вместо приемников использовались генераторы сигналов сделанные из ардуино нано.<br />
<br />
Использование устройства предполагает соблюдение техники безопасности и разумных мер предосторожности. Автор проекта никакой ответственности ни за что не несет.<br />
<br />
Есть еще один момент. При переключении управления с одного приемника на другой возможно изменение длительности отдельного управляющего импульса. Его длительность может оказаться меньше 1000 микросекунд или больше 2000 микросекунд. Сервоприводы достаточно медлительные устройства. Проблем быть не должно. Тем не менее эта особенность устройства может быть устранена. Только код придется писать уже на ассемблере.</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-83122975177459805712016-02-11T09:23:00.000-08:002016-02-11T09:23:24.840-08:00Измерение скорости реакции<div dir="ltr" style="text-align: left;" trbidi="on">
Скорость реакции достаточно важная штука. Например, при управлении автомобилем она играет далеко не последнюю роль. Есть масса факторов влияющих на скорость реакции. Сильная усталость и некоторые лекарства вызывают снижение скорости реакции. Вот я и решил сделать устройство, которое позволило бы измерить скорость реакции.<br />
<div>
<br /></div>
<div>
<a name='more'></a><br /></div>
<div>
<div>
Для начала отвечу на главный вопрос. Зачем делать устройство для измерения скорости реакции? Действительно, скорость реакции можно измерить на некоторых сайтах в интернете. Ещё можно написать программу для компьютера, которая будет решать ту же задачу. Не смотря на сказанное, в изготовлении специального устройства есть смысл. Во-первых, устройство на ардуино может работать без интернета. Во-вторых, сложно оценить погрешность решений реализованных на компьютере. Микроконтроллер в этом случае является более предсказуемым и простым вариантом. В-третьих, реализация такого устройства не требует много времени и ресурсов.</div>
<div>
<br /></div>
<div>
Итак. Железо.</div>
<div>
<br /></div>
<div>
Ардуино нано.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMCdBlsCxv5otpfm4yS7q8QA9FGyqWHCipiIhuKOX5jhRlbwAtNualGbE-8fpvKgSrb66fE4oZ8CszyVBfSHyAtCXOicwmpCu_S68Y-xKokYpLWFYcYgRMBgtrcAevn3E1fbhJjsJMrhGd/s1600/46902.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMCdBlsCxv5otpfm4yS7q8QA9FGyqWHCipiIhuKOX5jhRlbwAtNualGbE-8fpvKgSrb66fE4oZ8CszyVBfSHyAtCXOicwmpCu_S68Y-xKokYpLWFYcYgRMBgtrcAevn3E1fbhJjsJMrhGd/s400/46902.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Кнопка.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaUvhYcOJkFhm3DTLTXqqudK-0oq-plPIG4qFCR4Q5hv-o7enJbNZQRsnKFiKRnaoEXZ4laV1fTB_ZTDHZ65Gt9vysirgaJA9zfLLP0K6NfLVS8xTw5EoNRj5EFv7SVVG7yg82CYsC8QEr/s1600/42181.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaUvhYcOJkFhm3DTLTXqqudK-0oq-plPIG4qFCR4Q5hv-o7enJbNZQRsnKFiKRnaoEXZ4laV1fTB_ZTDHZ65Gt9vysirgaJA9zfLLP0K6NfLVS8xTw5EoNRj5EFv7SVVG7yg82CYsC8QEr/s400/42181.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Светодиод.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZrFOZ-XjgKc2mf7bh9Ob7g0ayjHvOrLOv2PsCVacgdGvfNRFfx7MhyphenhyphenLMKvk9sS8j3mDyS3ONBXRph4SHolvVTPgh55ht00PgJy3x0lau5E3OhKOdjvu5mfwQP38ss33urua6_dUhRxbE2/s1600/42201.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZrFOZ-XjgKc2mf7bh9Ob7g0ayjHvOrLOv2PsCVacgdGvfNRFfx7MhyphenhyphenLMKvk9sS8j3mDyS3ONBXRph4SHolvVTPgh55ht00PgJy3x0lau5E3OhKOdjvu5mfwQP38ss33urua6_dUhRxbE2/s400/42201.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div>
Соединение модулей.</div>
<div>
<br /></div>
<div>
arduino --- button</div>
<div>
VCC --- VCC</div>
<div>
GND --- GND</div>
<div>
A0 --- OUT</div>
<div>
<br /></div>
<div>
arduino --- led</div>
<div>
VCC --- V</div>
<div>
D8 --- R</div>
<div>
<br /></div>
<div>
Схема того, что должно получится.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG7FTzMaX6h8tFk8aNq6IYLlgwg68g1q27siquRBC5l_nFtFJ7c-ZW9Q7j1VkKHwvNolyNzf-a1O1VkLOcQbXtJI9i3w6VUy2jckYBT2Z663WXV84AGerLOPxiJBM9PF94hVDZlGHBh-xi/s1600/schematic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG7FTzMaX6h8tFk8aNq6IYLlgwg68g1q27siquRBC5l_nFtFJ7c-ZW9Q7j1VkKHwvNolyNzf-a1O1VkLOcQbXtJI9i3w6VUy2jckYBT2Z663WXV84AGerLOPxiJBM9PF94hVDZlGHBh-xi/s400/schematic.png" width="226" /></a></div>
<div>
<br /></div>
<div>
<div>
Скетч.</div>
<div>
<br /></div>
<div>
<pre>////////////////////////
//
// Arduino
//
////////////////////////
//
// Sketch:
//
const unsigned char LED = 8; // Digital Pin 8
const unsigned char BUTTON = 14; // Analog Pin 0
unsigned long int time1 = 0;
unsigned long int time2 = 0;
void setup()
{
// Led initialization
pinMode(LED, OUTPUT);
// Button initialization
pinMode(BUTTON, INPUT);
// UART initialization
Serial.begin(9600);
// Pseudo-random number generator initialization
digitalWrite(LED, LOW);
while ( digitalRead(BUTTON) == HIGH ) ;
randomSeed(micros());
digitalWrite(LED, HIGH);
}
void loop()
{
digitalWrite(LED, HIGH);
delay(random(2000, 5000));
digitalWrite(LED, LOW);
time1 = micros();
while ( digitalRead(BUTTON) == HIGH ) ;
time2 = micros();
Serial.println(((time2-time1)/1000000.0), 6);
}
//
// End
//
////////////////////////</pre>
</div>
<div>
<br /></div>
<div>
Работает устройство следующим образом. После подачи питания загорается светодиод. Своего рода индикация готовности устройства к работе. При нажатии на кнопку светодиод гаснет. В этот момент происходит инициализация генератора псевдослучайных чисел. После задержки, длительность которой определяется генератором псевдослучайных чисел, светодиод загорается снова. Теперь нужно как можно быстрее нажать кнопку. Время прошедшее от включения светодиода и до нажатия кнопки является временем реакции. Результат можно увидеть в мониторе порта ардуино.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfMVvXo_EhC_7b3gTIF0rflwGFXF0Id2f4ccaEYQe646UIOBLBAwaPwCgbHAqxbKQk7FYDEnz2eufqOjPXMlN-H-kpCHj_aGwZ2Aof7CgqKziBZuVucKisaB_riEcsT9Mh5840YzsXUsMt/s1600/img_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfMVvXo_EhC_7b3gTIF0rflwGFXF0Id2f4ccaEYQe646UIOBLBAwaPwCgbHAqxbKQk7FYDEnz2eufqOjPXMlN-H-kpCHj_aGwZ2Aof7CgqKziBZuVucKisaB_riEcsT9Mh5840YzsXUsMt/s400/img_1.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Генератор псевдослучайных чисел весьма необходимая в данном проекте вещь. Без него удается довольно неплохо натренироваться нажимать кнопочку в нужное время.</div>
<div>
<br /></div>
<div>
В заключении скажу несколько слов о том, что можно изменить, улучшить. Во-первых, можно повысить точность. Для этого нужно отказаться от использования стандартных библиотек ардуино. Только я немного сомневаюсь в целесообразности всего этого. Лично моя реакция не настолько быстра. Правда и сложностей в модификации программы не много. Если будет большой интерес к устройству - сделаю.</div>
<div>
<br /></div>
<div>
Во-вторых, можно сделать устройство более компактным и мобильным. Ардуино нано легко меняется на ардуино про мини. Вместо вывода данных через UART можно выводить результаты на какой нибудь экранчик. Получится небольшое и самодостаточное устройство.</div>
</div>
</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-35140573036092554392016-02-05T14:40:00.000-08:002016-02-05T14:57:28.456-08:00Шаговый двигатель и Arduino (часть 4)<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
Еще одна статья о шаговом двигателе. На этот раз речь пойдет о микрошаговом режиме управления двигателем. Вариантов реализации микрошагового режима очень много. В статье описывается одно из возможных решений.</div>
<div>
<br /></div>
<div>
<a name='more'></a><br /></div>
<div>
Для начала приведу перечень используемого железа.</div>
<div>
<br /></div>
<div>
Шаговый двигатель:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ8E12nxvReVnymozj6TXm14bANGXPeqkOxEjFKjJHS2hipcVPUUGkglbmHTvLkXWbXPt0y_sT-zeYrtVKVehx9eTrosr4o83FBXRPwr7zIT3lQ1vTIOSKrmWMSZF45UuUScP2UhjBKWo5/s1600/motor_4.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="357" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ8E12nxvReVnymozj6TXm14bANGXPeqkOxEjFKjJHS2hipcVPUUGkglbmHTvLkXWbXPt0y_sT-zeYrtVKVehx9eTrosr4o83FBXRPwr7zIT3lQ1vTIOSKrmWMSZF45UuUScP2UhjBKWo5/s400/motor_4.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
Драйвер шагового двигателя:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkleMGpvjfMJSc9j9Xxq5EiQ9oaBhyIIdSAZHcFqFxsGA6U_EQ9rfcBrthXpT4_JAMiyoAknn9XkkCzrV5RHxcLTN_UdICQjOrjJcds4o8wrGQCDyqNOyEj76qqfIoukd5qc94XQ258Lk_/s1600/IMG_0166.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkleMGpvjfMJSc9j9Xxq5EiQ9oaBhyIIdSAZHcFqFxsGA6U_EQ9rfcBrthXpT4_JAMiyoAknn9XkkCzrV5RHxcLTN_UdICQjOrjJcds4o8wrGQCDyqNOyEj76qqfIoukd5qc94XQ258Lk_/s400/IMG_0166.JPG" width="400" /></a></div>
<br /></div>
<div>
Ардуино уно:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKDh8HeUebxRnrfhHQ9cmC6Jj50JfI510NOZu45nsWQ1GQV9bTOg7dIzOqBdzKADP6iBkwWOhTr_dp12Olpg_FHbZzz7WVLzLgW2C8jyUz5bOs6sxhdIZPKJn4-hNDNkCc3kcRoEnC5fie/s1600/IMG_0190.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKDh8HeUebxRnrfhHQ9cmC6Jj50JfI510NOZu45nsWQ1GQV9bTOg7dIzOqBdzKADP6iBkwWOhTr_dp12Olpg_FHbZzz7WVLzLgW2C8jyUz5bOs6sxhdIZPKJn4-hNDNkCc3kcRoEnC5fie/s400/IMG_0190.JPG" width="400" /></a></div>
<br /></div>
<div>
Модуль с кнопочками:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdkWq7m3_qdrvR-2m37bqThC-T7rT7URXfwK_D5Yz87FDekcZpHEKCKcFf6lJBlSfWCOOnEuDNeMIQ4ZxCLRqz_yGr0WayPCuZQnTa4FeXaLD54aSazFqavKC9fuDWWYhWpcD21fts5GOy/s1600/IMG_0182.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdkWq7m3_qdrvR-2m37bqThC-T7rT7URXfwK_D5Yz87FDekcZpHEKCKcFf6lJBlSfWCOOnEuDNeMIQ4ZxCLRqz_yGr0WayPCuZQnTa4FeXaLD54aSazFqavKC9fuDWWYhWpcD21fts5GOy/s400/IMG_0182.JPG" width="400" /></a></div>
<br /></div>
<div>
<div>
Соединяются компоненты согласно приведенным ниже инструкциям.</div>
<div>
<br /></div>
<div>
motor --- driver</div>
<div>
A1 --- A+</div>
<div>
A2 --- B+</div>
<div>
B1 --- A-</div>
<div>
B2 --- B-</div>
<div>
VCC --- VIN</div>
<div>
<br /></div>
<div>
driver --- arduino</div>
<div>
GND --- GND</div>
<div>
EN1 --- D13</div>
<div>
EN2 --- D12</div>
<div>
IN1 --- D11</div>
<div>
IN2 --- D10</div>
<div>
IN3 --- D9</div>
<div>
IN4 --- D8</div>
<div>
<br /></div>
<div>
arduino --- button module</div>
<div>
VCC --- VCC</div>
<div>
GND --- GND</div>
<div>
A0 --- SW1</div>
<div>
A1 --- SW2</div>
<div>
<br /></div>
<div>
Питается драйвер двигателя от 9 вольтового блока питания.</div>
<div>
<br /></div>
<div>
driver --- power supply (DC 9V)</div>
<div>
VIN --- + 9 V</div>
<div>
GND --- GND</div>
<div>
<br /></div>
<div>
Ардуино получает питание через USB разъем.</div>
<div>
<br /></div>
<div>
Программа. Ниже приводится упрощенная версия. Я посчитал этот вариант более понятным.</div>
<div>
<br /></div>
<div>
<pre>////////////////////////
//
// Arduino Uno
//
////////////////////////
//
// Sketch: Stepper Motor
//
// Arduino --- ATmega328
//
// D13 --- Port B Pin 5
// D12 --- Port B Pin 4
// D11 --- Port B Pin 3
// D10 --- Port B Pin 2
// D9 --- Port B Pin 1
// D8 --- Port B Pin 0
//
// D7 --- Port D Pin 7
// D6 --- Port D Pin 6
// D5 --- Port D Pin 5
// D4 --- Port D Pin 4
// D3 --- Port D Pin 3
// D2 --- Port D Pin 2
// D1 --- Port D Pin 1
// D0 --- Port D Pin 0
//
// A5 --- Port C Pin 5
// A4 --- Port C Pin 4
// A3 --- Port C Pin 3
// A2 --- Port C Pin 2
// A1 --- Port C Pin 1
// A0 --- Port C Pin 0
#include <util/delay.h>
#define MOTOR_DDR DDRB
#define MOTOR_PORT PORTB
#define MOTOR_PIN PINB
#define EN1 5
#define EN2 4
#define IN1 3
#define IN2 2
#define IN3 1
#define IN4 0
#define BUTTON_DDR DDRC
#define BUTTON_PORT PORTC
#define BUTTON_PIN PINC
#define SW2 1
#define SW1 0
unsigned char step = 1;
unsigned char i;
void step1 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
_delay_ms(10);
}
void step2 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN2);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN2);
_delay_us(500);
}
}
void step3 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
_delay_ms(10);
}
void step4 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN1);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN1);
_delay_us(500);
}
}
void step5 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
_delay_ms(10);
}
void step6 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN1);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN1);
_delay_us(500);
}
}
void step7 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
_delay_ms(10);
}
void step8 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN2);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN2);
_delay_us(500);
}
}
void step9 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(1<<IN4));
_delay_ms(10);
}
void step10 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN2);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN2);
_delay_us(500);
}
}
void step11 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
_delay_ms(10);
}
void step12 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN1);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN1);
_delay_us(500);
}
}
void step13 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
_delay_ms(10);
}
void step14 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN1);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN1);
_delay_us(500);
}
}
void step15 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
_delay_ms(10);
}
void step16 (void)
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
for (i=0; i<10; i++)
{
MOTOR_PORT |= (1<<EN2);
_delay_us(500);
MOTOR_PORT &= ~(1<<EN2);
_delay_us(500);
}
}
void setup()
{
// Buttons initialization
BUTTON_DDR &= ~((1<<SW2)|(1<<SW1));
BUTTON_PORT &= ~((1<<SW2)|(1<<SW1));
// Motor initialization
MOTOR_DDR |= ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
MOTOR_PORT |= ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
}
void loop()
{
if ( (BUTTON_PIN & (1<<SW1)) == 0 ) step += 1;
if ( (BUTTON_PIN & (1<<SW2)) == 0 ) step -= 1;
if ( step == 0 ) step = 16;
if ( step == 17 ) step = 1;
if ( step == 1 ) step1();
if ( step == 2 ) step2();
if ( step == 3 ) step3();
if ( step == 4 ) step4();
if ( step == 5 ) step5();
if ( step == 6 ) step6();
if ( step == 7 ) step7();
if ( step == 8 ) step8();
if ( step == 9 ) step9();
if ( step == 10 ) step10();
if ( step == 11 ) step11();
if ( step == 12 ) step12();
if ( step == 13 ) step13();
if ( step == 14 ) step14();
if ( step == 15 ) step15();
if ( step == 16 ) step16();
}
//
// End
//
////////////////////////</pre>
</div>
<div>
<br /></div>
<div>
Для увеличения числа шагов используется ШИМ. Число шагов можно сделать любым. Только нужно иметь в виду, что сила трения не позволит перемещать вал двигателя очень маленькими шажками. Минимально возможный размер шага зависит от конкретного шагового двигателя.</div>
<div>
<br /></div>
<div>
У микрошагового режима есть еще одна интересная особенность. Вал двигателя крутится более плавно. Вибрации снижаются.</div>
<div>
<br /></div>
<div>
Приведенная выше программа является вполне рабочей, но использовать её стоит исключительно в ознакомительных целях.</div>
<div>
<br /></div>
<div>
Я написал более подходящий для использования в различных устройствах код.</div>
<div>
<br /></div>
<div>
<pre>////////////////////////
//
// Arduino Uno
//
////////////////////////
//
// Sketch: Stepper Motor
//
// Arduino --- ATmega328
//
// D13 --- Port B Pin 5
// D12 --- Port B Pin 4
// D11 --- Port B Pin 3
// D10 --- Port B Pin 2
// D9 --- Port B Pin 1
// D8 --- Port B Pin 0
//
// D7 --- Port D Pin 7
// D6 --- Port D Pin 6
// D5 --- Port D Pin 5
// D4 --- Port D Pin 4
// D3 --- Port D Pin 3
// D2 --- Port D Pin 2
// D1 --- Port D Pin 1
// D0 --- Port D Pin 0
//
// A5 --- Port C Pin 5
// A4 --- Port C Pin 4
// A3 --- Port C Pin 3
// A2 --- Port C Pin 2
// A1 --- Port C Pin 1
// A0 --- Port C Pin 0
#define MOTOR_DDR DDRB
#define MOTOR_PORT PORTB
#define MOTOR_PIN PINB
#define EN1 5
#define EN2 4
#define IN1 3
#define IN2 2
#define IN3 1
#define IN4 0
#define BUTTON_DDR DDRC
#define BUTTON_PORT PORTC
#define BUTTON_PIN PINC
#define SW2 1
#define SW1 0
const unsigned char speed = 10;
volatile unsigned char step = 1;
volatile unsigned char width1 = 60;
volatile unsigned char width2 = 60;
volatile unsigned char i = 0;
volatile unsigned char j = 0;
void setup()
{
// Buttons
BUTTON_DDR &= ~((1<<SW2)|(1<<SW1));
BUTTON_PORT &= ~((1<<SW2)|(1<<SW1));
// Motor
MOTOR_DDR |= ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
MOTOR_PORT |= ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
// Timer/Counter 2
TCNT2 = 0;</pre>
<pre> // COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
TCCR2A = 0;</pre>
<pre> // FOC2A FOC2B - - WGM22 CS22 CS21 CS20
TCCR2B = (1<<CS20);</pre>
<pre> // - - - - - OCIE2B OCIE2A TOIE2
TIMSK2 = (1<<TOIE2);</pre>
<pre> // - - - - - OCF2B OCF2A TOV2
TIFR2 = (1<<TOV2);
}
void loop()
{
}
ISR(TIMER2_OVF_vect)
{
if ( i == 0 )
{
MOTOR_PORT |= (1<<EN1);
MOTOR_PORT |= (1<<EN2);
}
if ( i == width1 )
{
MOTOR_PORT &= ~(1<<EN1);
}
if ( i == width2 )
{
MOTOR_PORT &= ~(1<<EN2);
}
i += 1;
if ( i == 60 )
{
i = 0;
j += 1;
if ( step == 1 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(1<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 2 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 60;
width2 = 30;
}
if ( step == 3 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 4 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 30;
width2 = 60;
}
if ( step == 5 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 6 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 30;
width2 = 60;
}
if ( step == 7 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 8 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(0<<IN3)|(1<<IN4));
width1 = 60;
width2 = 30;
}
if ( step == 9 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(1<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 10 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 60;
width2 = 30;
}
if ( step == 11 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 12 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(0<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 30;
width2 = 60;
}
if ( step == 13 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(1<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 14 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 30;
width2 = 60;
}
if ( step == 15 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 60;
width2 = 60;
}
if ( step == 16 )
{
MOTOR_PORT = ((1<<EN1)|(1<<EN2)|(0<<IN1)|(1<<IN2)|(1<<IN3)|(0<<IN4));
width1 = 60;
width2 = 30;
}
}
if ( j == speed )
{
j = 0;
if ( (BUTTON_PIN & (1<<SW1)) == 0 ) step += 1;
if ( (BUTTON_PIN & (1<<SW2)) == 0 ) step -= 1;
if ( step == 0 ) step = 16;
if ( step == 17 ) step = 1;
}
}
//
// End
//
////////////////////////</pre>
</div>
<div>
<br /></div>
<div>
Всё управление двигателем выполняется обработчиком прерывания по переполнению таймера/счетчика 2.</div>
<div>
<br /></div>
<div>
Частота ШИМ составляет около 1 килогерца.</div>
<div>
<br /></div>
<div>
Обработчик прерывания по переполнению таймера/счетчика 2 вызывается через</div>
<div>
<br /></div>
<div>
(1.0 / 16000000.0) * 256.0 * 1000.0 = 0.016 ms</div>
<div>
<br /></div>
<div>
Для формирования одного периода ШИМ необходимо вызвать обработчик 60 раз</div>
<div>
<br /></div>
<div>
(1.0 / 16000000.0) * 256.0 * 1000.0 * 60.0 = 0.96 ms</div>
<div>
<br /></div>
<div>
Таким образом частота ШИМ получается</div>
<div>
<br /></div>
<div>
1.0 / 0.96 = 1.042 KHz</div>
<div>
<br /></div>
<div>
Все приведенные в этой статье программы будут работать только в ардуино с микроконтроллером ATmega328 или ATmega168.</div>
</div>
</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-18242869399003530172016-01-09T13:48:00.000-08:002016-01-09T14:10:29.735-08:00Управление роботом<div dir="ltr" style="text-align: left;" trbidi="on">
В прошлой статье я рассказал о своем новом роботе. Теперь попытаюсь объяснить, как связано изменение положения робота в пространстве с управляющим программным кодом. Делается это для того, чтобы можно было заранее рассчитать маршрут и иметь возможность переместить робота в нужное место.<br />
<br />
<a name='more'></a><br />
Начну с самого простого. Движение по прямой. Для перемещения платформы на некоторое расстояние вперед необходимо, чтобы правый и левый двигатели повернули колеса на одинаковый угол вперед.<br />
<br />
Представленная ранее программа позволяет перемещать валы шаговых двигателей установленных в платформе на 3.75 градуса. Диаметр используемых колес составляет 65 миллиметров. Значит длина их окружности составляет 65.0 * 3.14 = 204.1 миллиметра. Так как 3.75 градуса это 360.0 / 3.75 = 96.0 часть окружности, то поворот на 3.75 градуса приведет к перемещению на 204.1 / 96.0 = 2.13 миллиметра.<br />
<br />
(65.0 * 3.14) / (360.0 / 3.75) = 2.13 мм<br />
<br />
Таким образом с каждой итерацией робот будет перемещаться на 2.13 миллиметра вперед.<br />
<br />
При движении назад колеса нужно крутить в другую сторону. А всё остальное абсолютно тоже.<br />
<br />
С поворотами всё немного сложнее. Ниже приведено схематичное изображение платформы. Благодаря этой картинке объяснить процесс поворота сильно проще.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivjtEIHxb_mVHotRPc7qVzSkDnTuCyGGVP0U7s9q1ev0zIYneT5uw5ZPbI9oyPIw5hDjvaOt9xS4zzKYmVTqjpgrLi1zBWaRsUm4DuvpD5UbxccHT69PqFWMjN6czYLAZkimdQyi6DfeTE/s1600/img_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivjtEIHxb_mVHotRPc7qVzSkDnTuCyGGVP0U7s9q1ev0zIYneT5uw5ZPbI9oyPIw5hDjvaOt9xS4zzKYmVTqjpgrLi1zBWaRsUm4DuvpD5UbxccHT69PqFWMjN6czYLAZkimdQyi6DfeTE/s400/img_1.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Чтобы робот повернуть налево нужно, чтобы правый двигатель повернул правое колесо (R) на некоторый угол вперед, а левый двигатель повернул левое колесо (L) на тот же угол назад. При этом траектория движения колес будет представлять собой окружность (K). Платформа будет поворачиваться вокруг центра этой окружности. На схеме обозначен буквой A. Диаметр окружности K равен расстоянию от центра правого колеса до центра левого колеса. У меня это 135 миллиметров. Длина этой окружности 135.0 * 3.14 = 423.9 миллиметров. Если правое и левое колесо повернется на 3.75 градуса, то робот проедет по окружности K 2.13 миллиметра. А 2.13 миллиметра составляют 423.9 / 2.13 = 199.0 часть окружности K. Таким образом робот повернется на 360.0 / 199.0 = 1.81 градус.</div>
<div>
<br /></div>
<div>
360.0 / ((135.0 * 3.14) / 2.13) = 1.81</div>
<div>
<br /></div>
<div>
Для поворота на 90 градусов потребуется около 50 итераций.</div>
<div>
<br /></div>
<div>
90.0 / (360.0 / ((135.0 * 3.14) / 2.13)) = 49.75</div>
<div>
<br /></div>
<div>
Число не целое. Нужно округлять.</div>
<div>
<br /></div>
<div>
(360.0 / ((135.0 * 3.14) / 2.13)) * 50.0 = 90.45</div>
<div>
<br /></div>
<div>
Ровно 90 градусов не получается, но результат достаточно близок к желаемому.</div>
<div>
<br /></div>
<div>
Для поворота направо необходимо правое колесо крутить назад, а левое - вперед. На этом отличия заканчиваются.</div>
<div>
<br /></div>
<div>
Есть ещё один способ изменения направления движения платформы. В программе он не реализован, но рассказать про него стоит. Всего возможно четыре варианта выполнения этого поворота: вперед налево, назад направо, вперед направо, назад налево. Я подробно расскажу только о выполнении поворота вперед налево. Здесь тоже не обойтись без картиночки.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6Y6TnMeTf7PQqADyJQS4Ud9w2OgENjBFkoidIOdi13tIPwgsTgVeC1RGMVDOB9Imxezo83b2WpiMfAY21Kz80-aAqN4nxNDQAUJL17atwyo3Vbxf41TCx51r61AGBFKmoE3KzbCIGCYsw/s1600/img_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6Y6TnMeTf7PQqADyJQS4Ud9w2OgENjBFkoidIOdi13tIPwgsTgVeC1RGMVDOB9Imxezo83b2WpiMfAY21Kz80-aAqN4nxNDQAUJL17atwyo3Vbxf41TCx51r61AGBFKmoE3KzbCIGCYsw/s400/img_2.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
В данном случае правый двигатель поворачивает правое колесо вперед, а левый двигатель препятствует прокручиванию левого колеса. Теперь только правое колесо будет двигаться по окружности. На схеме эта окружность обозначена буквой K. Центр окружности K совпадает с центром левого колеса. Поворот выполняется вокруг центра левого колеса. Таким образом радиус окружности K равен расстоянию от центра правого колеса до центра левого колеса. Как и раньше это 135 миллиметров. Но диаметр окружности K теперь 135.0 * 2.0 = 270.0 миллиметров. Длина этой окружности равна 270.0 * 3.14 = 847.8 миллиметров. При повороте правого колеса на 3.75 градуса, оно проедет по окружности K 2.13 миллиметра. Это будет 847.8 / 2.13 = 398.0 часть окружности. Робот повернется на 360.0 / 398.0 = 0.9 градуса.</div>
<div>
<br /></div>
<div>
360.0 / ((135.0 * 2.0 * 3.14) / 2.13) = 0.9</div>
<div>
<br /></div>
<div>
Этот способ позволяет с большей точностью управлять платформой, но требует больше свободного пространства.</div>
<div>
<br /></div>
<div>
Теперь самое главное. Я описал идеальную платформу, передвигающуюся по идеальной поверхности. Реальный робот не будет двигаться так как описано. Это связано с недостатками комплектующих, погрешностями сборки, неоднородностью поверхности по которой передвигается робот.</div>
<div>
<br /></div>
<div>
Используемые мной шаговые двигатели имеют шаг в 7.5 градуса. На самом деле длина отдельного шага может быть 7.51 или 7.49 градусов. При этом за 48 шагов вал двигателя повернется на 360 градусов. Не смотря на различную длину шага, ошибка не накапливается. Но в рассматриваемом проекте длина отдельного шага важна.</div>
<div>
<br /></div>
<div>
Колеса установленные на платформе могут иметь различный диаметр. Даже если разница ничтожна, при прохождении длинного маршрута отклонения будут существенными.</div>
<div>
<br /></div>
<div>
А ещё моя сборка очень далека от идеала. Колеса расположены под небольшим углом. Это очень сильно влияет на движение платформы.</div>
<div>
<br /></div>
<div>
Только не нужно пытаться построить идеальную платформу. Занятие это неблагодарное. И не потому, что идеал недостижим в принципе. Просто робот будет передвигаться по неидеальному покрытию: неровному, пыльному, скользкому. Естественно колеса будут проскальзывать. А даже незаметные проскальзывания, со временем, существенно повлияют на положение робота.</div>
<div>
<br /></div>
<div>
Итак. Чем больше робот двигается, тем больше его реальное положение отличается от расчетного. Решить эту проблему можно с помощью некой системы, позволяющей узнать место нахождения робота. Это может быть система локального позиционирования, система маяков или система ориентации в пространстве основанная на машинном зрении. Вариантов немало.</div>
</div>
</div>Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-77579796725179799062016-01-02T15:16:00.000-08:002016-02-05T15:01:37.249-08:00Новый робот<div dir="ltr" style="text-align: left;" trbidi="on">
В этой статье я расскажу о своем новом роботе. Есть ряд вопросов на которые мне хочется найти ответ. Новая платформа должна мне помочь в этом. Начну с описания механики, электроники и простой программы.<br />
<div>
<br /></div>
<div>
<a name='more'></a><br /></div>
<div>
К сожалению видео получилось не очень. Снимаю мало. Разбираться в тонкостях нет ни времени, ни желания. Видно что недостаточно света. Освещение искусственное. Можно это исправить настройками? Менять освещение? Я понятия не имею. Как нибудь постараюсь разобраться. С естественным освещением сейчас тоже не очень. Дни короткие и пасмурные.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/SHQFDpCVXRA/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/SHQFDpCVXRA?feature=player_embedded" width="320"></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div>
Схема обычная. Трехколесная. Сделана из подручных материалов. Что можно приклеить на двусторонний скотч, то клеится на скотч. Пластиковые стяжки наше всё. Болты и гайки это последнее средство. У такого подхода есть как достоинства так и недостатки. Для изготовления небольшого прототипа это вполне приемлемые решения.</div>
<div>
<br /></div>
<div>
Фото 1</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixvF5wOBStK6cpiEmwTqGsYRQJ-Iq7SqqsiofHLHbxZStqKlqYcgh2ouUm0EtT_7_-uy1L2mz98cwHKs-Pre0K7oX9p3IK6tpMB1XeHxB-PGbS7Cl59iL8HBXm3expL4qadJ6hWt3GviCs/s1600/IMG_0001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixvF5wOBStK6cpiEmwTqGsYRQJ-Iq7SqqsiofHLHbxZStqKlqYcgh2ouUm0EtT_7_-uy1L2mz98cwHKs-Pre0K7oX9p3IK6tpMB1XeHxB-PGbS7Cl59iL8HBXm3expL4qadJ6hWt3GviCs/s400/IMG_0001.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
Фото 2</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrxoXtngA4akEPSD9FCC5aEaowleWvAky14SIFL3wXXUTMWV102JlWe8K2YZGeVJPyXDwxOzyWBR8Ny9Lr4eQ3dsehOzLslBlDjkgA7MQhh_VmmkvvB6vfYKahiU7rm1yl1asleMhDfJls/s1600/IMG_0002.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrxoXtngA4akEPSD9FCC5aEaowleWvAky14SIFL3wXXUTMWV102JlWe8K2YZGeVJPyXDwxOzyWBR8Ny9Lr4eQ3dsehOzLslBlDjkgA7MQhh_VmmkvvB6vfYKahiU7rm1yl1asleMhDfJls/s400/IMG_0002.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Фото 3</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiScIFhTHPhXcjYxSWknmfKDLt77A6qRxYYxSohUFQgZUvpRnBIzpUUdLESY5OzhKd81ed9ugB9hTzCXigbBsZ1cGZuCEg0S1RojKjMfWnW7JjDk-lfWQ3jM3qgQwPCfTPB8k-us13mb9QD/s1600/IMG_0003.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiScIFhTHPhXcjYxSWknmfKDLt77A6qRxYYxSohUFQgZUvpRnBIzpUUdLESY5OzhKd81ed9ugB9hTzCXigbBsZ1cGZuCEg0S1RojKjMfWnW7JjDk-lfWQ3jM3qgQwPCfTPB8k-us13mb9QD/s400/IMG_0003.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Фото 4</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj5RL-axzaPq5N3pUEMqstBEW7rMaA0YHIPaguZDMeOeAliwy5IV2STGK9dVAHItDk3Bl4dGRkfmFaPTR_Ay4OrXnexO7vuxT_ka4uKy9e4Y5la36TP3geBqEp-e4MfO0rE0Js1iKvttEN/s1600/IMG_0004.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj5RL-axzaPq5N3pUEMqstBEW7rMaA0YHIPaguZDMeOeAliwy5IV2STGK9dVAHItDk3Bl4dGRkfmFaPTR_Ay4OrXnexO7vuxT_ka4uKy9e4Y5la36TP3geBqEp-e4MfO0rE0Js1iKvttEN/s400/IMG_0004.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
В этой платформе используются шаговые двигатели.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOGxWx4hEDqKYQs0M6EJ4Ds_UFmv_Emmnu7ihhbEmjSFwWbOJQvHvWU1yxYr38OKAR2EYWyeAZDTfwUiIfTYntFrtCrzS-IUO419FslC6OCDdn5uudiUDcmBNMpqPgP6qwDjN5B-S5Jyg9/s1600/motor.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="357" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOGxWx4hEDqKYQs0M6EJ4Ds_UFmv_Emmnu7ihhbEmjSFwWbOJQvHvWU1yxYr38OKAR2EYWyeAZDTfwUiIfTYntFrtCrzS-IUO419FslC6OCDdn5uudiUDcmBNMpqPgP6qwDjN5B-S5Jyg9/s400/motor.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Крепежные отверстия моторов рассчитаны на болтики 2.5 мм. Их днем с огнем не найдешь. Покупайте сразу вместе с моторами у китайцев.</div>
<div>
<br /></div>
<div>
Переходники для крепления колес под трех миллиметровый вал.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD5ufa1F1Z5Q5CAKQYXvanqs0J1NFKRGJo-WblGvbxjmerS4rdih1LSJ1Zv4ZCMMHw7UvhUm3dEXABWDE5HBGwc8LK3n84q1VtF9F53nzSm47cXc6sBVB5ZBdexCj7_gRXTyh8Z48Wu6Fo/s1600/hex.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD5ufa1F1Z5Q5CAKQYXvanqs0J1NFKRGJo-WblGvbxjmerS4rdih1LSJ1Zv4ZCMMHw7UvhUm3dEXABWDE5HBGwc8LK3n84q1VtF9F53nzSm47cXc6sBVB5ZBdexCj7_gRXTyh8Z48Wu6Fo/s400/hex.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Мои переходники свободно одеваться не захотели. Пришлось помочь тисочками.</div>
<div>
<br />
Колеса от радиоуправляемых моделей автомобилей масштаба 1/10.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi65izyKRZ6eKDcYFhM3mjSu6TOC6uZO200x223Tj9qmbYmSa74L9ky26Y3_q2kYrbXjq6wB48bgX-R8JQbhxmacWU3XU_uQPUxqK7WrSKSDpkyyYrXWvuWPYt21p1h15Nj-C0ytKrGpll9/s1600/wheel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi65izyKRZ6eKDcYFhM3mjSu6TOC6uZO200x223Tj9qmbYmSa74L9ky26Y3_q2kYrbXjq6wB48bgX-R8JQbhxmacWU3XU_uQPUxqK7WrSKSDpkyyYrXWvuWPYt21p1h15Nj-C0ytKrGpll9/s400/wheel.jpg" width="400" /></a></div>
<br />
Внешний диаметр колеса (Outer Diameter): 65 mm<br />
Диаметр пластикового диска (Wheel Diameter): 52 mm<br />
Размер переходника (Wheel Drive Hex): 12 mm<br />
Ширина колеса (Wheel Width): 26 mm<br />
<br /></div>
<div>
Для управления моторами используются готовые драйвера на L293D. Они дешевые. И к ним просто подключить моторы. Есть все нужные разъемы. Не нужно ничего паять.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4hhO_tX7-GDkXI5gLCJUw-0XJSNri5alhbmouIz65IEHFNuCGMdi_HIoRcKVOtW76ZTdMQacKEtQ3fIv3mUV4-1LnCKgZ1h_1EP86SxQGE92hCWzGBnTpF7VWnY8wRSH2e9LP6EMi7MMh/s1600/driver.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4hhO_tX7-GDkXI5gLCJUw-0XJSNri5alhbmouIz65IEHFNuCGMdi_HIoRcKVOtW76ZTdMQacKEtQ3fIv3mUV4-1LnCKgZ1h_1EP86SxQGE92hCWzGBnTpF7VWnY8wRSH2e9LP6EMi7MMh/s400/driver.JPG" width="400" /></a></div>
<div>
<div>
<br /></div>
<div>
Драйверами двигателей управляет ардуино уно.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9akxUIZDY63Vd0sFm4hCzbonqXEcXBSdhS7y5w6Eg7j0Jci0r-QtCxnbGfmLXHQwC8N7cBx6gvvPhKyKUAjeinwCt3tFCQvGBYkYVTKkhfmMjqZeF92wnZqqWO6pXIJEgDWIIe600mIbf/s1600/arduino.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9akxUIZDY63Vd0sFm4hCzbonqXEcXBSdhS7y5w6Eg7j0Jci0r-QtCxnbGfmLXHQwC8N7cBx6gvvPhKyKUAjeinwCt3tFCQvGBYkYVTKkhfmMjqZeF92wnZqqWO6pXIJEgDWIIe600mIbf/s400/arduino.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Для удобства используется Arduino UNO Sensor Shield V5</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkJmEAd_GBP0MkeWE0dfujrdyYrhgnO7aXQPjoPerLpy0Pai0_yJeCTzY2sViyI2Ns_4Tpgep03AxB6AmSwsp5DyI4SXSaz-POqR8AQ-GCgkP7xZOlQWV5_aXK4EpNISyxDVKCvuy6CSgz/s1600/shield.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkJmEAd_GBP0MkeWE0dfujrdyYrhgnO7aXQPjoPerLpy0Pai0_yJeCTzY2sViyI2Ns_4Tpgep03AxB6AmSwsp5DyI4SXSaz-POqR8AQ-GCgkP7xZOlQWV5_aXK4EpNISyxDVKCvuy6CSgz/s400/shield.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Интересная платка. Есть клеммы для подключения аккумулятора. Если напряжение выдаваемое аккумулятором превышает 5 вольт, то необходимо удалить перемычку с SEL. Иначе ардуино сгорит. При этом ардуино останется без питания. Можно запитать уно от того же аккумулятора, но через стабилизатор самой ардуино. Выводы шилда vcc расположенные рядом с цифровыми пинами всегда соединены непосредственно с аккумулятором. На них будет тоже напряжение, что и на аккумуляторе. А вот на выводах vcc находящихся рядом с аналоговыми пинами будут 5 вольт выдаваемые стабилизатором ардуино. Перед подключением всякого разного к шилду не повредит и напряжение мультиметром проверить.</div>
<div>
<br /></div>
<div>
Питается робот от двух соединенных последовательно Li-ion аккумуляторов 18650.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8KrpSkllPpgMXyAsxMFNCu_4V1rTmPVfWXH4wFhtsOdtiEZApMK38MBbdRuDsA5-dRHDx_idRM3iOIMKbCsMIyckDdAFb8eVzoOKb7MGUKs1j1YT99e4_itcsg4KkPQ0JR6jRV9AkraAE/s1600/SKU084219a.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8KrpSkllPpgMXyAsxMFNCu_4V1rTmPVfWXH4wFhtsOdtiEZApMK38MBbdRuDsA5-dRHDx_idRM3iOIMKbCsMIyckDdAFb8eVzoOKb7MGUKs1j1YT99e4_itcsg4KkPQ0JR6jRV9AkraAE/s400/SKU084219a.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Обратите внимание на то, что эти аккумуляторы пожароопасны и взрывоопасны. Заряжать их следует только специальным зарядным устройством (процесс необходимо постоянно контролировать лично). Также их нельзя разряжать ниже определенного напряжения. При падении напряжения ниже некоторого порога, такие аккумуляторы выходят из строя. Для разных моделей литиевых аккумуляторов величина минимального напряжения различна. Поэтому настоятельно рекомендуется использовать защищенные аккумуляторы. В них встроена специальная платка предотвращающая критический разряд и перезаряд аккумулятора. Однако абсолютная безопасность при использовании таких аккумуляторов не гарантируется. Тщательно проверяйте все цепи своих конструкций перед подключением литиевых аккумуляторов. Аккумуляторы должны быть способны выдать ток потребляемый устройством. Это должен быть штатный режим работы аккумулятора, а не кратковременно допустимый пиковый ток. Иначе ничего хорошего не ждите.</div>
<div>
<br /></div>
<div>
Моя конструкция потребляет около 1.5 ампера.</div>
<div>
<br /></div>
<div>
Одной обмотке моего шагового двигателя нужно</div>
<div>
(4.2 + 4.2) / 26.0 = 0.323 A</div>
<div>
<br /></div>
<div>
При одновременной запитке двух обмоток будет</div>
<div>
0.323 * 2.0 = 0.646 A</div>
<div>
<br /></div>
<div>
В платформе используется два двигателя</div>
<div>
0.646 * 2.0 = 1.292 A</div>
<div>
<br /></div>
<div>
Не стоит забывать об ардуино и драйверах двигателей. Им тоже нужен ток.</div>
<div>
<br /></div>
<div>
Неплохо бы предусмотреть запас для дополнительного оборудования (разные сенсоры).</div>
<div>
<br /></div>
<div>
Итого. Ток разряда аккумулятора должен быть более 3 амперов. Я заказал себе аккумуляторы с током разряда в 30 ампер. Для данного проекта многовато, но у меня на них большие планы. Когда получу, напишу.</div>
<div>
<br /></div>
<div>
Для аккумуляторов 18650 есть специальные батарейные отсеки.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWmBXrMmD364qOektp4oF5z1DtZiv04Pdqh2yOkJMmMDZM8Ih43HqUxlPIwTWmnvFqNneJ3KzIueu98GbIQIj2LO9LktV6z_qTua2c9r4rbgWceNetIGcVNDBmE4z357e5Po4usqUfN17/s1600/battery.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWmBXrMmD364qOektp4oF5z1DtZiv04Pdqh2yOkJMmMDZM8Ih43HqUxlPIwTWmnvFqNneJ3KzIueu98GbIQIj2LO9LktV6z_qTua2c9r4rbgWceNetIGcVNDBmE4z357e5Po4usqUfN17/s400/battery.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Подавать питание на ардуино удобно через Power Plug Connector Adapter 2.1*5.5 mm</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLhoU6vvs5pwk2bED5Hs7hJdNinLz7ZWJZ5vFHhHuf0e_YslcVx6HHgMdMpJzZhRNb2wuqZfufNPxNRjV3G9rUMPGGywrXZ2ESTRTuQ7O4fU9tChSj0YJlH49FLImCEVk81pGukvWODiRb/s1600/connector.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLhoU6vvs5pwk2bED5Hs7hJdNinLz7ZWJZ5vFHhHuf0e_YslcVx6HHgMdMpJzZhRNb2wuqZfufNPxNRjV3G9rUMPGGywrXZ2ESTRTuQ7O4fU9tChSj0YJlH49FLImCEVk81pGukvWODiRb/s400/connector.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Закончу рассказ об электрической части описанием соединений компонентов.</div>
<div>
<br /></div>
<div>
Подключение шагового двигателя к драйверу.</div>
<div>
<br /></div>
<div>
stepper motor --- driver</div>
<div>
A1 --- A+</div>
<div>
A2 --- A-</div>
<div>
B1 --- B+</div>
<div>
B2 --- B-</div>
<div>
VCC --- VIN</div>
<div>
<br /></div>
<div>
Питание драйвера двигателя.</div>
<div>
<br /></div>
<div>
driver --- battery (7.4 V)</div>
<div>
VIN --- +</div>
<div>
GND --- -</div>
<div>
<br /></div>
<div>
Настройки драйвера двигателя.</div>
<div>
<br /></div>
<div>
driver --- driver</div>
<div>
EN1 --- VCC</div>
<div>
EN2 --- VCC</div>
<div>
<br /></div>
<div>
Подключение драйвера правого двигателя к ардуино.</div>
<div>
<br /></div>
<div>
driver --- arduino uno</div>
<div>
GND --- GND</div>
<div>
IN1 --- D11</div>
<div>
IN2 --- D10</div>
<div>
IN3 --- D9</div>
<div>
IN4 --- D8</div>
<div>
<br /></div>
<div>
Подключение драйвера левого двигателя к ардуино.</div>
<div>
<br /></div>
<div>
driver --- arduino uno</div>
<div>
GND --- GND</div>
<div>
IN1 --- A3</div>
<div>
IN2 --- A2</div>
<div>
IN3 --- A1</div>
<div>
IN4 --- A0</div>
<div>
<br /></div>
<div>
Код. В данной статье я приведу лишь простую тестовую программу.</div>
<div>
<br /></div>
<div>
<pre>////////////////////////
//
// Arduino Uno
//
////////////////////////
//
// Sketch: Robot
//
#include <util/delay.h>
const unsigned char D1_IN1 = 11; // Digital Pin 11
const unsigned char D1_IN2 = 10; // Digital Pin 10
const unsigned char D1_IN3 = 9; // Digital Pin 9
const unsigned char D1_IN4 = 8; // Digital Pin 8
const unsigned char D2_IN1 = 17; // Analog Pin 3
const unsigned char D2_IN2 = 16; // Analog Pin 2
const unsigned char D2_IN3 = 15; // Analog Pin 1
const unsigned char D2_IN4 = 14; // Analog Pin 0
const unsigned char FORWARD = 1;
const unsigned char BACKWARD = 2;
const unsigned char RIGHT = 3;
const unsigned char LEFT = 4;
unsigned char step1 = 1;
unsigned char step2 = 1;
void driver1 (unsigned char direct)
{
if ( direct == 1 ) step1 -= 1;
if ( direct == 2 ) step1 += 1;
if ( step1 == 0 ) step1 = 8;
if ( step1 == 9 ) step1 = 1;
if ( step1 == 1 )
{
digitalWrite(D1_IN1, LOW);
digitalWrite(D1_IN2, HIGH);
digitalWrite(D1_IN3, HIGH);
digitalWrite(D1_IN4, HIGH);
}
if ( step1 == 2 )
{
digitalWrite(D1_IN1, LOW);
digitalWrite(D1_IN2, LOW);
digitalWrite(D1_IN3, HIGH);
digitalWrite(D1_IN4, HIGH);
}
if ( step1 == 3 )
{
digitalWrite(D1_IN1, HIGH);
digitalWrite(D1_IN2, LOW);
digitalWrite(D1_IN3, HIGH);
digitalWrite(D1_IN4, HIGH);
}
if ( step1 == 4 )
{
digitalWrite(D1_IN1, HIGH);
digitalWrite(D1_IN2, LOW);
digitalWrite(D1_IN3, LOW);
digitalWrite(D1_IN4, HIGH);
}
if ( step1 == 5 )
{
digitalWrite(D1_IN1, HIGH);
digitalWrite(D1_IN2, HIGH);
digitalWrite(D1_IN3, LOW);
digitalWrite(D1_IN4, HIGH);
}
if ( step1 == 6 )
{
digitalWrite(D1_IN1, HIGH);
digitalWrite(D1_IN2, HIGH);
digitalWrite(D1_IN3, LOW);
digitalWrite(D1_IN4, LOW);
}
if ( step1 == 7 )
{
digitalWrite(D1_IN1, HIGH);
digitalWrite(D1_IN2, HIGH);
digitalWrite(D1_IN3, HIGH);
digitalWrite(D1_IN4, LOW);
}
if ( step1 == 8 )
{
digitalWrite(D1_IN1, LOW);
digitalWrite(D1_IN2, HIGH);
digitalWrite(D1_IN3, HIGH);
digitalWrite(D1_IN4, LOW);
}
}
void driver2 (unsigned char direct)
{
if ( direct == 1 ) step2 -= 1;
if ( direct == 2 ) step2 += 1;
if ( step2 == 0 ) step2 = 8;
if ( step2 == 9 ) step2 = 1;
if ( step2 == 1 )
{
digitalWrite(D2_IN1, LOW);
digitalWrite(D2_IN2, HIGH);
digitalWrite(D2_IN3, HIGH);
digitalWrite(D2_IN4, HIGH);
}
if ( step2 == 2 )
{
digitalWrite(D2_IN1, LOW);
digitalWrite(D2_IN2, LOW);
digitalWrite(D2_IN3, HIGH);
digitalWrite(D2_IN4, HIGH);
}
if ( step2 == 3 )
{
digitalWrite(D2_IN1, HIGH);
digitalWrite(D2_IN2, LOW);
digitalWrite(D2_IN3, HIGH);
digitalWrite(D2_IN4, HIGH);
}
if ( step2 == 4 )
{
digitalWrite(D2_IN1, HIGH);
digitalWrite(D2_IN2, LOW);
digitalWrite(D2_IN3, LOW);
digitalWrite(D2_IN4, HIGH);
}
if ( step2 == 5 )
{
digitalWrite(D2_IN1, HIGH);
digitalWrite(D2_IN2, HIGH);
digitalWrite(D2_IN3, LOW);
digitalWrite(D2_IN4, HIGH);
}
if ( step2 == 6 )
{
digitalWrite(D2_IN1, HIGH);
digitalWrite(D2_IN2, HIGH);
digitalWrite(D2_IN3, LOW);
digitalWrite(D2_IN4, LOW);
}
if ( step2 == 7 )
{
digitalWrite(D2_IN1, HIGH);
digitalWrite(D2_IN2, HIGH);
digitalWrite(D2_IN3, HIGH);
digitalWrite(D2_IN4, LOW);
}
if ( step2 == 8 )
{
digitalWrite(D2_IN1, LOW);
digitalWrite(D2_IN2, HIGH);
digitalWrite(D2_IN3, HIGH);
digitalWrite(D2_IN4, LOW);
}
}
void robot (unsigned char command, unsigned char i)
{
unsigned char direct1, direct2;
if (command == FORWARD)
{
direct1 = 2;
direct2 = 1;
}
if (command == BACKWARD)
{
direct1 = 1;
direct2 = 2;
}
if (command == RIGHT)
{
direct1 = 1;
direct2 = 1;
}
if (command == LEFT)
{
direct1 = 2;
direct2 = 2;
}
while( i > 0 )
{
i -= 1;
driver1(direct1);
driver2(direct2);
_delay_ms(20);
}
}
void driver1_init (void)
{
pinMode(D1_IN1, OUTPUT);
pinMode(D1_IN2, OUTPUT);
pinMode(D1_IN3, OUTPUT);
pinMode(D1_IN4, OUTPUT);
digitalWrite(D1_IN1, LOW);
digitalWrite(D1_IN2, HIGH);
digitalWrite(D1_IN3, HIGH);
digitalWrite(D1_IN4, HIGH);
}
void driver2_init (void)
{
pinMode(D2_IN1, OUTPUT);
pinMode(D2_IN2, OUTPUT);
pinMode(D2_IN3, OUTPUT);
pinMode(D2_IN4, OUTPUT);
digitalWrite(D2_IN1, LOW);
digitalWrite(D2_IN2, HIGH);
digitalWrite(D2_IN3, HIGH);
digitalWrite(D2_IN4, HIGH);
}
void setup()
{
driver1_init();
driver2_init();
_delay_ms(2000);
}
void loop()
{
robot(FORWARD, 50);
_delay_ms(1000);
robot(BACKWARD, 50);
_delay_ms(1000);
robot(LEFT, 50);
_delay_ms(1000);
robot(RIGHT, 50);
_delay_ms(1000);
}
//
// End
//
////////////////////////</pre>
</div>
<div>
<br /></div>
<div>
В заключении скажу несколько слов о достоинствах и недостатках получившейся конструкции.</div>
<div>
<br /></div>
<div>
Момент развиваемый шаговым двигателем не зависит от частоты вращения вала. Момент является максимальным в довольно широком диапазоне скоростей. Частоту вращения вала коллекторного двигателя можно регулировать с помощью ШИМ. Но при этом меняется и момент развиваемый двигателем. Чем ниже частота вращения вала, тем меньше момент.</div>
<div>
<br /></div>
<div>
Колеса можно крепить непосредственно на вал шагового двигателя. Правда перед этим неплохо бы измерить момент развиваемый двигателем. С коллекторными моторами колеса соединяются только через редуктор.</div>
<div>
<br /></div>
<div>
Шаговые двигатели позволяют достаточно точно позиционировать платформу. С коллекторными двигателями добиться такой точности перемещения можно только при использовании энкодеров.</div>
<div>
<br /></div>
<div>
Шаговые двигатели имеют больший ресурс нежели коллекторные моторы. Фактически срок службы шаговых двигателей определяется ресурсом подшипников. В коллекторных моторах, помимо подшипников, изнашивается и коллектор. Правда во всех моих моторчиках стоят втулки. </div>
<div>
<br /></div>
<div>
Из минусов можно отметить цену. Мощные шаговые двигатели не дешевле сравнимых коллекторных моторов с редукторами.</div>
<div>
<br /></div>
<div>
Для платформы на коллекторных моторах достаточно было бы одного драйвера на L293D. А для платформы на шаговых двигателях нужно два драйвера.</div>
<div>
<br /></div>
<div>
Число ножек ардуино отведенных под управление шаговыми двигателями составляет 8. В платформе с коллекторными моторами достаточно 4.</div>
<div>
<br /></div>
<div>
Потребление энергии. Неподвижный коллекторный мотор не расходует энергию. Шаговый двигатель потребляет ток даже тогда, когда стоит. Впрочем это зависит от управляющей программы. Правда если обесточить все обмотки шагового двигателя, момент на валу существенно снизится.</div>
<div>
<br /></div>
<div>
Ещё мне не очень нравится как робот движется. Но это скорее тоже связано с программой. Попробую добиться более плавного движения используя микрошаговый режим управления шаговым двигателем.</div>
<div>
<br /></div>
<div>
Возможно добавлю один элемент в батарею. Это приведет к увеличению момента развиваемого моторами. Дождусь хороших аккумуляторов, тогда и будет видно.</div>
<div>
<br /></div>
<div>
Последнее. Хранение литиевых аккумуляторов. Элементы 18650 нужно хранить в специальных пластиковых контейнерах. Это защитит их от механических повреждений и короткого замыкания.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimRdbIFfAsIIyGf-rTVMWbcc47yVD3w_mwgE-8872140MdD4PtBcgrcHZ4MR5q-Zv1dJQnAo_ocfDap5frL3Fxbqj3lucYhy9mnU3RSlSegizaScIsLVWYeYjAJkhcDNgoqb5tQ8U8S2sb/s1600/box.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimRdbIFfAsIIyGf-rTVMWbcc47yVD3w_mwgE-8872140MdD4PtBcgrcHZ4MR5q-Zv1dJQnAo_ocfDap5frL3Fxbqj3lucYhy9mnU3RSlSegizaScIsLVWYeYjAJkhcDNgoqb5tQ8U8S2sb/s400/box.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Контейнеры с батареями не помешает сложить в специальный огнеупорный пакет.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQpdnPZ5F3QrxSts4VqjvWd2bKXv7Icww11nudizebdPcwj2sz3pBjZRMa092NAp6RQ4zniFxfvpoJ40OrOamS9NJyo8RcCsEaUlRa-zEWSlJeTY_pcEzeG7Z8GP5YSa2ax0y_f77ghyphenhyphenBO/s1600/bag.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQpdnPZ5F3QrxSts4VqjvWd2bKXv7Icww11nudizebdPcwj2sz3pBjZRMa092NAp6RQ4zniFxfvpoJ40OrOamS9NJyo8RcCsEaUlRa-zEWSlJeTY_pcEzeG7Z8GP5YSa2ax0y_f77ghyphenhyphenBO/s400/bag.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
И всё это лучше держать подальше от легковоспламеняющихся вещей.</div>
<div>
<br /></div>
<div>
Соблюдайте технику безопасности. Берегите себя и своих близких.</div>
</div>
</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-33822010408000349302015-10-16T17:04:00.001-07:002015-10-16T17:29:24.839-07:00Дистанционно управляемая машинка<div dir="ltr" style="text-align: left;" trbidi="on">
В этой статье рассказывается, как сделать простую дистанционно управляемую платформу. В проекте используются исключительно модули ардуино.<br />
<br />
<a name='more'></a><br />
Видео.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/5lPqgEfBtvo/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/5lPqgEfBtvo?feature=player_embedded" width="320"></iframe></div>
<div>
<br /></div>
<div>
<div>
Про саму платформу я уже рассказывал ранее. Здесь скажу лишь пару слов. Два коллекторных моторчика с редукторами. Три колеса. По колесику на мотор-редуктор и одно опорное. У меня платформа самодельная, но можно купить готовую.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYmWdJT4va1e04_PU1cisnEsn1P_GeyjJwomOZPHLE3j0nTjDYD7aEGTH9-lQDlutXkAGVSKJ7VYZXgrMJPhbAMUrSbzRL6ego3nmasHmSqld5I8GcqZeZXklwh93nVUJH7xuW6jBHLuNF/s1600/arduino_robot_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYmWdJT4va1e04_PU1cisnEsn1P_GeyjJwomOZPHLE3j0nTjDYD7aEGTH9-lQDlutXkAGVSKJ7VYZXgrMJPhbAMUrSbzRL6ego3nmasHmSqld5I8GcqZeZXklwh93nVUJH7xuW6jBHLuNF/s400/arduino_robot_2.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Единственное я бы рекомендовал поискать платформы с мотор-редукторами помедленнее. Такие платформы лучше подходят для обучения. Для высоких скоростей существуют другие решения.</div>
<div>
<br /></div>
<div>
Мозгом платформы является arduino nano.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtCgMTWt-7S0v6F9ws6LNy54kh376ING7_3XaXifeYL_vxPVzcn4l_23DEey-sD9oHIhdzVwbE0LdWAldcB5jKUFgfM5zlSDeBdoS4i8xTs0Z5QBlWNnejF949o-L0SdXt6iM4Au3ocpds/s1600/nano_m168.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtCgMTWt-7S0v6F9ws6LNy54kh376ING7_3XaXifeYL_vxPVzcn4l_23DEey-sD9oHIhdzVwbE0LdWAldcB5jKUFgfM5zlSDeBdoS4i8xTs0Z5QBlWNnejF949o-L0SdXt6iM4Au3ocpds/s400/nano_m168.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Для удобства подключения используется arduino nano sensor shield.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpQLbuF6N9VQIWdY5FUp3A9gIMGJoD0lCbNWUUVHVWuT6p2SM6ZZlM8QxCS2mHHG6PZfXycT5Z-2WNN1nzmX0FLMGD4kS0Z9dsEag8pc_hI1WPcIxQp-yxDdBvsvCjSxxcfZonNOg2377b/s1600/s1600.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpQLbuF6N9VQIWdY5FUp3A9gIMGJoD0lCbNWUUVHVWuT6p2SM6ZZlM8QxCS2mHHG6PZfXycT5Z-2WNN1nzmX0FLMGD4kS0Z9dsEag8pc_hI1WPcIxQp-yxDdBvsvCjSxxcfZonNOg2377b/s400/s1600.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Драйвер двигателей на L9110S.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkoE5XxLIC8aHTsnaxuNJkv4c1rz5vc3DuebdFiSEnIS7-r7SAPzFrxnahqdcZS5kAQSi3fVV9vcT7fvMcVmQmsNNOHVTzqjg1TAZFNcal2_CrESo5Az5KbaSdRQCvNNjjCr5K_iLWc2gm/s1600/l9110s.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkoE5XxLIC8aHTsnaxuNJkv4c1rz5vc3DuebdFiSEnIS7-r7SAPzFrxnahqdcZS5kAQSi3fVV9vcT7fvMcVmQmsNNOHVTzqjg1TAZFNcal2_CrESo5Az5KbaSdRQCvNNjjCr5K_iLWc2gm/s400/l9110s.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
И приемник.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ8LmqxniRaQQlOLnva-o1l_uNOojtJxWtzpG-k6B56jlHX7krMpqnQuKWEGqk94XnB5qqSKqFkESpLkgXF8LiY1dezCVe76uge0HkqnAc3XCtk81lQZVJr7sUMuAIXKNUTDmMssBXwYL3/s1600/tsop_38.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ8LmqxniRaQQlOLnva-o1l_uNOojtJxWtzpG-k6B56jlHX7krMpqnQuKWEGqk94XnB5qqSKqFkESpLkgXF8LiY1dezCVe76uge0HkqnAc3XCtk81lQZVJr7sUMuAIXKNUTDmMssBXwYL3/s400/tsop_38.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Соединяется всё согласно изложенным ниже инструкциям.</div>
<div>
<br /></div>
<div>
Левый двигатель подключаются к клеммам MOTOR-A. Правый двигатель подключается к клеммам MOTOR-B. Какая клемма мотора с какой клеммой драйвера соединяется, нужно определять опытным путем.</div>
<div>
<br /></div>
<div>
Arduino --- Motor Driver</div>
<div>
GND --- GND</div>
<div>
VCC --- VCC</div>
<div>
D8 --- B-IB</div>
<div>
D9 --- B-IA</div>
<div>
D10 --- A-IB</div>
<div>
D11 --- A-IA</div>
<div>
<br /></div>
<div>
Arduino Nano --- IR Receiver</div>
<div>
GND --- GND</div>
<div>
VCC --- VCC</div>
<div>
D2 --- OUT</div>
<div>
<br /></div>
<div>
Питается платформа от четырех, соединенных последовательно, NiMH аккумуляторов по 1.2 вольта каждый.</div>
<div>
<br /></div>
<div>
Основой пульта также является arduino nano.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtCgMTWt-7S0v6F9ws6LNy54kh376ING7_3XaXifeYL_vxPVzcn4l_23DEey-sD9oHIhdzVwbE0LdWAldcB5jKUFgfM5zlSDeBdoS4i8xTs0Z5QBlWNnejF949o-L0SdXt6iM4Au3ocpds/s1600/nano_m168.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtCgMTWt-7S0v6F9ws6LNy54kh376ING7_3XaXifeYL_vxPVzcn4l_23DEey-sD9oHIhdzVwbE0LdWAldcB5jKUFgfM5zlSDeBdoS4i8xTs0Z5QBlWNnejF949o-L0SdXt6iM4Au3ocpds/s400/nano_m168.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Модуль с кнопочками.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGvqw1-a5UCfJhbfrV4ndu64-xQXIqgHlGNYXRtjxH6OVqQ6RGVSiUkhY-5quRYY-GRy4NPrjdlY6iYWgkGcIb6IEYkzqPQJyzMiTLH5ObFDpkMAWLMIhndsmR6so5dwJyC84NbbVHq9_A/s1600/button_7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="397" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGvqw1-a5UCfJhbfrV4ndu64-xQXIqgHlGNYXRtjxH6OVqQ6RGVSiUkhY-5quRYY-GRy4NPrjdlY6iYWgkGcIb6IEYkzqPQJyzMiTLH5ObFDpkMAWLMIhndsmR6so5dwJyC84NbbVHq9_A/s400/button_7.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
ИК передатчик.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwJXsWgk1ChRBg5Gr1QD0dDoZi1XmTgZMu96FtEo4qaG_5stuLi_0HOKXBjtYgIISjnAoimP63W-xMPJbJ2_ib6TxNJtN-JD0Q7VnZi_bRoi1Smv2Hv85yLbeFvlE79kdE6mZLxx5O0hT5/s1600/42200.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwJXsWgk1ChRBg5Gr1QD0dDoZi1XmTgZMu96FtEo4qaG_5stuLi_0HOKXBjtYgIISjnAoimP63W-xMPJbJ2_ib6TxNJtN-JD0Q7VnZi_bRoi1Smv2Hv85yLbeFvlE79kdE6mZLxx5O0hT5/s400/42200.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Схема.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcYAOhSWVnxfwqDF5terkHA8SwpXgey6GN0vlALhTSs0z_wU44b5swYc2nnKpCqqphdGA4BXIKafJe0KINiKjUnXgLHkqmH1CkJUrRVzYvLLd_o4c72624re-D3R8gzgVOG_OBoBEuLnVB/s1600/schematic_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcYAOhSWVnxfwqDF5terkHA8SwpXgey6GN0vlALhTSs0z_wU44b5swYc2nnKpCqqphdGA4BXIKafJe0KINiKjUnXgLHkqmH1CkJUrRVzYvLLd_o4c72624re-D3R8gzgVOG_OBoBEuLnVB/s400/schematic_0.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Этот ИК передатчик обеспечивает связь на пару метров. Но есть и более дальнобойная версия.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6QoxtU7BL5nQkO73OeXwb71OMQML9cCcrRRwL7YtBULH2s_EerGHq1EAQ8c-mnnLzhfwExyFn7zFIMPc17ky8x5BeWYXOEhl38-MmFq_Xuktvl39_lzfDjzhH6BzLmKtLWd9ILTkRgywk/s1600/42300.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6QoxtU7BL5nQkO73OeXwb71OMQML9cCcrRRwL7YtBULH2s_EerGHq1EAQ8c-mnnLzhfwExyFn7zFIMPc17ky8x5BeWYXOEhl38-MmFq_Xuktvl39_lzfDjzhH6BzLmKtLWd9ILTkRgywk/s400/42300.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Схема.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSp7ZNqyVyhA8qHZ54YWFMcL9mc0zY9C7tLjbex8dwyZUUdYptX6M21AcFZVHE-h_04HRcJZjH62A3d4C0MRE4adXA8zOv2nFXN8vMuJxogs4Z3K_Dt992MLr7oNfsAC0jauxi3NcQFxIj/s1600/schematic_11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSp7ZNqyVyhA8qHZ54YWFMcL9mc0zY9C7tLjbex8dwyZUUdYptX6M21AcFZVHE-h_04HRcJZjH62A3d4C0MRE4adXA8zOv2nFXN8vMuJxogs4Z3K_Dt992MLr7oNfsAC0jauxi3NcQFxIj/s400/schematic_11.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
По расстоянию ничего конкретного сказать не могу. Нет у меня такого модуля. Без сомнений оно больше, но насколько...</div>
<div>
<br /></div>
<div>
Есть ещё одна модификация ИК передатчика.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdjc9L0YwykthMZKTd5PXnE3wwU0CF0KNPUlMSEKaYkU__lrHcUbscGvNNRzud5MZcirFdrMm9KKfyAlwCtFvaHuUevxyFkoezqO7E2UN2YySCMNii1Li_VJaZbJQX2SQ4Q0Rp4KPahB5b/s1600/42400.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdjc9L0YwykthMZKTd5PXnE3wwU0CF0KNPUlMSEKaYkU__lrHcUbscGvNNRzud5MZcirFdrMm9KKfyAlwCtFvaHuUevxyFkoezqO7E2UN2YySCMNii1Li_VJaZbJQX2SQ4Q0Rp4KPahB5b/s400/42400.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Схема.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUOnxOAUdF8esemGMsglwToC5PwUYJspXGknSels3oPixfopeTy3_k8gDNZb-_KWPO21VrASs80wtg4rqwkSC3ABO0VWRAviNvzwD4vjXIN9MXUxcFEFwnDTSRAd5Td7Uj1D9nlsFbeLE8/s1600/schematic_12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUOnxOAUdF8esemGMsglwToC5PwUYJspXGknSels3oPixfopeTy3_k8gDNZb-_KWPO21VrASs80wtg4rqwkSC3ABO0VWRAviNvzwD4vjXIN9MXUxcFEFwnDTSRAd5Td7Uj1D9nlsFbeLE8/s400/schematic_12.png" width="283" /></a></div>
<div>
<br /></div>
<div>
<div>
Не думаю, что это хороший выбор для данного проекта. Такой модуль скорее предназначен для универсальной станции управления.</div>
<div>
<br /></div>
<div>
При наличии желания можно самостоятельно сделать довольно мощный ИК передатчик.</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLtN64iJnGbANMP8r-R7Muv3DsVjzmdFt2zo0UhvEMvftwji0bw-sySLUvXdlbEdmNQ5Z6sIuY2j64DatWPc_Gb4d5bedLn3jZFMpvXBd7M6yXTtTe5WhTb4QZQ5UFt7sTW141kMHV3RTE/s1600/schematic_20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLtN64iJnGbANMP8r-R7Muv3DsVjzmdFt2zo0UhvEMvftwji0bw-sySLUvXdlbEdmNQ5Z6sIuY2j64DatWPc_Gb4d5bedLn3jZFMpvXBd7M6yXTtTe5WhTb4QZQ5UFt7sTW141kMHV3RTE/s400/schematic_20.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<div>
Резистор R2 можно взять и поменьше. На 22 Ом. В любом случае он должен быть достаточно мощным. Минимум 1 Вт. R1 и R3 достаточно 0.25 Вт. Включать этот модуль можно лишь в импульсном режиме.</div>
<div>
<br /></div>
<div>
Ниже приводятся инструкции по соединению модулей.</div>
<div>
<br /></div>
<div>
Arduino --- Button module</div>
<div>
A0 --- SW1</div>
<div>
A1 --- SW2</div>
<div>
A2 --- SW3</div>
<div>
A4 --- SW4</div>
<div>
VCC --- VCC</div>
<div>
GND --- GND</div>
<div>
<br /></div>
<div>
Arduino --- IR led module</div>
<div>
D8 --- DAT</div>
<div>
VCC --- VCC</div>
<div>
GND --- GND</div>
<div>
<br /></div>
<div>
У меня пульт питается через USB разъем. Но ничто не мешает запитать его от тех же четырех аккумуляторов NiMH.</div>
<div>
<br /></div>
<div>
Скетч для платформы.</div>
<div>
<br /></div>
<div>
<pre>////////////////////////
//
// Arduino Nano
//
////////////////////////
//
// Sketch: IR receiver
//
const unsigned char A_IA = 8;
const unsigned char A_IB = 9;
const unsigned char B_IA = 10;
const unsigned char B_IB = 11;
const unsigned long int CODE1 = 0b10000001;
const unsigned long int CODE2 = 0b10000010;
const unsigned long int CODE3 = 0b10000100;
const unsigned long int CODE4 = 0b10001000;
const unsigned long int CODE5 = 0b10010000;
const unsigned long int CODE6 = 0b10100000;
volatile unsigned char data = 0;
volatile unsigned char temp = 0;
volatile unsigned char count = 0;
volatile unsigned long int time1 = 0;
volatile unsigned long int time2 = 0;
volatile unsigned long int period = 0;
void forward_forward( void )
{
digitalWrite(A_IA, HIGH);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, HIGH);
digitalWrite(B_IB, LOW);
}
void backward_backward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, HIGH);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, HIGH);
}
void forward_stop( void )
{
digitalWrite(A_IA, HIGH);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, LOW);
}
void stop_forward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, HIGH);
digitalWrite(B_IB, LOW);
}
void backward_stop( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, HIGH);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, LOW);
}
void stop_backward( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, HIGH);
}
void stop_stop( void )
{
digitalWrite(A_IA, LOW);
digitalWrite(A_IB, LOW);
digitalWrite(B_IA, LOW);
digitalWrite(B_IB, LOW);
}
void setup()
{
attachInterrupt(0, tsop, FALLING);
pinMode(A_IA, OUTPUT);
pinMode(A_IB, OUTPUT);
pinMode(B_IA, OUTPUT);
pinMode(B_IB, OUTPUT);
stop_stop();
}
void loop()
{
if ( data == CODE1 ) forward_stop();
if ( data == CODE2 ) backward_stop();
if ( data == CODE3 ) stop_backward();
if ( data == CODE4 ) stop_forward();
if ( data == CODE5 ) forward_forward();
if ( data == CODE6 ) backward_backward();
if ( data == 0 ) stop_stop();
data = 0;
delay(70);
}
void tsop()
{
time1 = micros();
period = time1 - time2;
time2 = time1;
temp <<= 1;
count += 1;
if ( period > 1500 ) temp |= 1;
if ( period > 15000 ) count = 0;
if ( count == 8 ) data = temp;
}
//
// End
//
////////////////////////</pre>
</div>
<div>
<br /></div>
<div>
Скетч для пульта.</div>
<div>
<br /></div>
<div>
<pre>////////////////////////
//
// Arduino Nano
//
////////////////////////
//
// Sketch: IR transmitter
//
// Arduino --- IR led module
// D8 --- DAT
// VCC --- VCC
// GND --- GND
// Arduino --- Button module
// A0 --- SW1
// A1 --- SW2
// A2 --- SW3
// A4 --- SW4
// VCC --- VCC
// GND --- GND
#include <util/delay.h>
const unsigned char CODE1 = 0b10000001;
const unsigned char CODE2 = 0b10000010;
const unsigned char CODE3 = 0b10000100;
const unsigned char CODE4 = 0b10001000;
const unsigned char CODE5 = 0b10010000;
const unsigned char CODE6 = 0b10100000;
volatile unsigned char count = 0;
void IR_send( unsigned char data )
{
for (char i=0; i<=8; i++)
{
TCCR2B = (1<<CS20);
if ( (data & 0b10000000) != 0 )
while ( count < 152 );
if ( (data & 0b10000000) == 0 )
while ( count < 76 );
TCCR2B = 0;
data <<= 1;
count = 0;
}
_delay_ms(23); // wait 23 ms
}
// Input/Output Ports initialization
void Ports_Init( void )
{
// Port B initialization
// - - PB5 PB4 PB3 PB2 PB1 PB0
DDRB = 0b00000001;
PORTB = 0b00000000;
// Port C initialization
// - - PC5 PC4 PC3 PC2 PC1 PC0
DDRC = 0b00000000;
PORTC = 0b00000000;
// Port D initialization
// PD7, PD6, PD5, PD4, PD3, PD2, PD1, PD0
DDRD = 0b00000000;
PORTD = 0b00000000;
}
// Timer/Counter 2 initialization
void Timer2_Init( void )
{
TCNT2 = 45;
// COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
TCCR2A = 0;
// FOC2A FOC2B - - WGM22 CS22 CS21 CS20
TCCR2B = 0;
// - - - - - OCIE2B OCIE2A TOIE2
TIMSK2 = (1<<TOIE2);
// - - - - - OCF2B OCF2A TOV2
TIFR2 = (1<<TOV2);
}
void setup()
{
// Global disable interrupts
cli();
// Input/Output Ports initialization
Ports_Init();
// Timer/Counter 2 initialization
Timer2_Init();
// Global enable interrupts
sei();
}
void loop()
{
if ( (PINC & 0b00001111) == 0b00001110 )
IR_send(CODE1);
if ( (PINC & 0b00001111) == 0b00001101 )
IR_send(CODE2);
if ( (PINC & 0b00001111) == 0b00001011 )
IR_send(CODE3);
if ( (PINC & 0b00001111) == 0b00000111 )
IR_send(CODE4);
if ( (PINC & 0b00001111) == 0b00000110 )
IR_send(CODE5);
if ( (PINC & 0b00001111) == 0b00001001 )
IR_send(CODE6);
}
ISR(TIMER2_OVF_vect)
{
TCNT2 += 45;
if ( count < 20 )
PORTB ^= 1;
count += 1;
}
//
// End
//
////////////////////////</pre>
</div>
<div>
<br /></div>
<div>
В этом проекте используется протокол ИК связи аналогичный описанному в <a href="http://justforduino.blogspot.ru/2014/01/blog-post.html" target="_blank">http://justforduino.blogspot.ru/2014/01/blog-post.html</a></div>
</div>
<div>
<br /></div>
<div>
<div>
Получилась простая и недорогая дистанционно управляемая платформа. Правда есть у неё и недостатки. Они свойственны ИК связи вообще. Дело в том, что такая связь работает в пределах одной комнаты. Стены непроницаемы для инфракрасного света. А на улице расстояние связи сокращается весьма существенно. Особенно в ясный солнечный день.</div>
</div>
</div>
Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0tag:blogger.com,1999:blog-5345940022723292631.post-61415777473184247832015-10-11T19:33:00.000-07:002015-10-11T19:35:27.547-07:00Шаговый двигатель и Arduino (часть 3)<div dir="ltr" style="text-align: left;" trbidi="on">
Решил написать о полушаговом режиме управления шаговым двигателем. Да. Ещё один способ управления двигателем.<br /><br />
<a name='more'></a><br />
Приведенные ранее программы управления позволяют установить вал моего шагового двигателя в сорок восемь фиксированных точек.<br />
<br />
360.0 / 7.5 = 48<br />
<br />
Программы из предыдущих статей перемещали вал шагового двигателя по шагам. Однако существует способ уменьшения перемещения вала шагового двигателя в два раза. Иначе говоря, можно перемещать вал на половину шага.<br />
<br />
7.5 / 2.0 = 3.75<br />
<br />
При этом число фиксированных положений в которые можно установить вал двигателя увеличивается до девяносто шести.<br />
<br />
360.0 / 3.75 = 96<br />
<br />
Это позволяет позиционировать вал двигателя с большей точностью.<br />
<br />
Программа<br />
<br />
<pre>////////////////////////
//
// Arduino Uno
//
////////////////////////
//
// Sketch: Stepper Motor
//
#include <util/delay.h>
const unsigned char IN1 = 11; // Digital Pin 11
const unsigned char IN2 = 10; // Digital Pin 10
const unsigned char IN3 = 9; // Digital Pin 9
const unsigned char IN4 = 8; // Digital Pin 8
const unsigned char SW1 = 14; // Analog Pin 0
const unsigned char SW2 = 15; // Analog Pin 1
unsigned char step = 1;
void setup()
{
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
}
void loop()
{
if ( digitalRead(SW1) == LOW ) step -= 1;
if ( digitalRead(SW2) == LOW ) step += 1;
if ( step == 0 ) step = 8;
if ( step == 9 ) step = 1;
if ( step == 1 )
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
}
if ( step == 2 )
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
}
if ( step == 3 )
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
}
if ( step == 4 )
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
if ( step == 5 )
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
if ( step == 6 )
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
if ( step == 7 )
{
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
if ( step == 8 )
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
_delay_ms(20);
}
//
// End
//
////////////////////////</pre>
<br />
Железо как в первой части. Подключается всё как описано во второй части.</div>Misha Shevchenkohttp://www.blogger.com/profile/12784048466787135218noreply@blogger.com0