kharlashkin Posted April 25, 2017 Author Share Posted April 25, 2017 (edited) @norkas, @Azbuka, Да вот как-то внятной инструкции не могу найти. Edited April 25, 2017 by kharlashkin @ Quote Link to comment Short link Share on other sites More sharing options...
Azbuka Posted April 25, 2017 Share Posted April 25, 2017 @norkas, @Azbuka, Да вот как-то внятной инструкции не могу найти.Есть такая книга. 1 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted April 25, 2017 Author Share Posted April 25, 2017 Есть такая книга. Спасибо. @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted April 26, 2017 Author Share Posted April 26, 2017 (edited) Модернизировал страничку загрузки скетча: 'run.py' from flask import Flask, render_template, request, flash, redirect import forms from flask_wtf.csrf import CSRFProtect from werkzeug import secure_filename import os, subprocess app = Flask(__name__) csrf = CSRFProtect(app) app.secret_key = '9\xd8\xcc\xdb\x9d(\x94\xbex\xc4*\xd5\x17\xcet\xad\xc7\xe7i\x92\xaf\xf1x\xa8' @app.route('/upload_sketch', methods=['GET', 'POST']) def upload_sketch(): form = forms.Avrdude() if form.validate_on_submit(): partno = request.form['partno'] port = request.form['port'] baudrate = request.form['baudrate'] programmer = request.form['programmer'] sketch = form.sketch.data filename = secure_filename(sketch.filename) sketch.save(os.path.join('/kharlashkin/Flask/uploads', filename)) cmd = 'avrdude -p ' + partno + ' -P ' + port + ' -b ' + baudrate + ' -c ' + programmer + ' -U flash:w:' + filename flash(cmd) PIPE = subprocess.PIPE p = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT, close_fds=True) while True: console = p.stdout.readline() if not console: break flash(console) os.remove('/kharlashkin/Flask/uploads' + '/' + filename) return redirect(request.url) elif form.errors: for fieldName, errorMessages in form.errors.iteritems(): for error in errorMessages: flash(error) return redirect(request.url) return render_template('upload_sketch.html', form=form) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000) 'forms.py' from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileRequired, FileAllowed from wtforms import SelectField import glob ports = glob.glob('/dev/tty[A-Za-z]*') class Avrdude(FlaskForm): partno = SelectField('partno', choices=[('m328', 'ATmega328'), ('m328p', 'ATmega328P'), ('m168', 'ATmega168'), ('m168p', 'ATmega168P'), ('m2560', 'ATmega2560 (**)'), ('m32u4', 'ATmega32U4'), ('t85', 'ATtiny85')]) baudrate = SelectField('baudrate', choices=[('9600', '9600'), ('19200', '19200'), ('38400', '38400'), ('57600', '57600'), ('74880', '74880'), ('115200', '115200'), ('230400', '230400'), ('250000', '250000')]) programmer = SelectField('programmer', choices=[('avrisp', 'Atmel AVR ISP'), ('avrispmkII', 'Atmel AVR ISP mkII'), ('arduino', 'Arduino'), ('usbtiny', 'USBtiny simple USB programmer'), ('usbasp', 'USBasp')]) sketch = FileField(validators=[FileRequired('No selected file'), FileAllowed(['hex'], 'Incorrect file format')]) port = SelectField('port', choices=[(i, i) for i in ports]) 'upload_sketch.html' {% extends "base.html" %} {% block content %} <h1>Загрузка скетча в Arduino</h1> <br> <form method="post" enctype="multipart/form-data"> {{ form.csrf_token }} {{ form.sketch }} <br> <strong>Микроконтроллер</strong> {{ form.partno }} <strong>Порт</strong> {{ form.port }} <strong>Скорость</strong> {{ form.baudrate }} <strong>Программатор</strong> {{ form.programmer }} <input type="submit" value="Загрузка"> </form> {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} <i> <br> {{ message }} </i> {% endfor %} {% endif %} {% endwith %} {% endblock %} 'base.html' <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>Свежий воздух</title> <!-- Bootstrap Core CSS --> <link href="static/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom CSS --> <style> body { padding-top: 70px; /* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */ } </style> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <!-- Navigation --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <div class="container"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/index">Свежий воздух</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li> <a href="#">About</a> </li> <li> <a href="#">Services</a> </li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Arduino<span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="/serial_monitor">Монитор порта</a></li> <li><a href="/upload_sketch">Загрузка скетча</a></li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </div> <!-- /.container --> </nav> <!-- Page Content --> <div class="container"> {% block content %} {% endblock %} </div> <!-- /.container --> <!-- jQuery Version 1.11.1 --> <script src="static/js/jquery.js"></script> <!-- Bootstrap Core JavaScript --> <script src="static/js/bootstrap.min.js"></script> </body> </html> Нужно попробовать монитор порта прикрутить ;) Edited April 26, 2017 by kharlashkin 2 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted May 8, 2017 Author Share Posted May 8, 2017 Может кто объяснить мне что это такое и как оно работает? Приехала железка, дополнительно к ней заказал микроконтроллер, который будет отслеживать "0" и рулить напряжением, но мой ноут не захотел видеть платку, а хаба под рукой не оказалось. Стационарный ПК под Win7 увидел нормально, буду пробовать завести что к чему. @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted May 12, 2017 Author Share Posted May 12, 2017 (edited) буду пробовать Наступил на некоторое количество граблей - опишу свой опыт. Грабли №1. Нормальной вменяемой инструкции "для чайников" нет, AliExpress дает вроде как две ссылки на RobotDyn, но они неправильные, в русском сегменте вообще нет этой железки, правильная ссылка на международный сайт - http://robotdyn.com/~jZEda. В свою очередь в качестве документации дается ссылка на instructables - Arduino Controlled Light Dimmer, где уважаемый diy_bloke, всесторонне довольно подробно расписывает что к чему. В принципе, данный пост я несколько раз прочел на этапе размышлений как же мне плавно управлять вентилятором. Но, может правда это только в моем случае, ни один из приведенного скетча у Вас не заработает! Пробовал это все дело подключать к Arduino Uno R3. Грабли №2. После 2-х ночей, и прочтения вот этой информации со "Школы для электриков", я подумал что вообще зря купил эту железку: Наиболее широкое применение в силовых электронных аппаратах получили фазовое (рис. 4,а,б) и широтно-импульсное управление тиристорами (рис. 4,в). Рис. 5. Вид напряжения на нагрузке при: а) – фазовом управлении тиристором; б) – фазовом управлении тиристором с принудительной коммутацией; в) – широтно-импульсном управлении тиристором В названии этого модуля явно указано PWM, соответственно только широтно-импульсном управление платка может. У меня уже был модуль с твердотельным реле, который можно примерно таким же образом использовать. В общем и целом пичалька. Код который заточен работать для пропуска полупериодов уже не помню где взял. Основная идея там счетчик перехода синусоиды через 0, и закрытие / открытие тиристора и обнуление счетчика. Как работает с вентилятором не понравилось - например, в течении 5 циклов, 4 идет на 100% и 1 цикл на 0% мощности. За счет инерции двигателя вентилятора возможно он и крутиться на 80% максимальной мощности. Но меня этот вариант не устраивал. Думаю, он хорош только для нагревателей. Грабли №3. Устав топтаться на одном месте и не высыпаясь, перешел ко второй части "Марлезонского балета", а именно к платке Digispark ATtiny85 MicroUSB. Практически сразу нашлась тема, где на этом чипе уже делали диммер. Захотелось попробовать прошить соответствующий скетч, но сработала "защита от дурака", подробнее в этом сообщении. Покопав исходники и погуглив - оказалось, что прошив данный скетч в ATtiny85, я потеряю возможность использовать функционал Digispark, и прошивать нужно только программатором или вот так незатейливо по инструкции с официального форума Arduino. Я так понимаю, что приведенный скетч использует внутренний таймер процессора, который так же используют Digispark для связи по usb с ПК. Самое интересное что я для себя вынес из этих уроков - ссылка в скетче ;) Voltage controlled dimmer with an ATtiny85. Которая привела меня куда нужно - AC Phase Control. Ко времени прочтения уже было полное понимание работы, тиристоров, схем, приведенных скетчей и инструкций. Именно эта картинка и дала толчок к правильному написанию нужного мне скетча: #define ControlSimistor 3 // Выход на симистор #define ControlZero 2 // Вход контроля перехода через 0 volatile byte dimming = 0; // Начальное значение мощности void setup() { pinMode(ControlSimistor, OUTPUT); digitalWrite(ControlZero, 1); // Активируем контроль перехода через 0 Serial.begin(57600); // Значения мощности через порт attachInterrupt(0, zero, RISING); // Внешнее прерывание контроля перехода через ноль } void zero() // Если есть переход через 0 { if (dimming >= 255) // Если задано максимальное значение { digitalWrite(ControlSimistor, HIGH); // Тиристор постоянно открыт } else if (dimming <= 0) // Если минимум { digitalWrite(ControlSimistor, LOW); // Тиристор закрыт } else if (dimming > 0 && dimming < 255) // Если не минимум и не максимум { digitalWrite(ControlSimistor, LOW); // Сначала закрываем delayMicroseconds((5100 - dimming * 20)); // Ждем digitalWrite(ControlSimistor, HIGH); // Открываем тиристор } } void loop() { if (Serial.available()) // Если порт открыт { dimming = Serial.parseInt(); // Считываем данные и находим в них целое число } } Ну, могу себя поздравить, на Arduino все работает как нужно! Буду пробовать прошивать в ATtiny85. Хочу кое-что прояснить. Изначально я испытывал полный цикл в 10 мс на полупериод, но учитывая особенности вентиляторов он начинает более-менее нормально крутить крыльчатку где-то с 45% мощности, именно поэтому задается такая задержка в начале полупериода до открытия тиристора + в дальнейшем буду использовать analogRead(). Edited May 12, 2017 by kharlashkin 2 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted May 18, 2017 Author Share Posted May 18, 2017 Буду пробовать прошивать в ATtiny85. Чет мне кажется спалил я тиньку или сбросил память в "0" - перепутал "+" с землей. Пока гуглю как прошить в неё загрузчик Digispark с помощью ардуинки. Имхо, управлять тиристором и считывать значения датчиков параллельно, наверное не самый лучший вариант - ресурсов не хватит. 2 @ Quote Link to comment Short link Share on other sites More sharing options...
SkepticalFox Posted May 29, 2017 Share Posted May 29, 2017 (edited) . Edited January 9, 2021 by SkepticalFox 2 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted May 30, 2017 Author Share Posted May 30, 2017 http://micropython.org/live/ Что-то очень прикольная штука для поиграться))) Читал когда-то на хабре про эту платку - отзывы были неоднозначны, ведь можно использовать те же малины, апельсины, бананы с полноценной операционной системой и полноценным python - примерно за те же деньги. На странице проекта выложены бинарники для ESP8266 и STM32F4 - а это уже интереснее :) Чет мне кажется спалил я тиньку или сбросил память в "0" - перепутал "+" с землей. Пробовал прошить загрузчик Digispark в плату несколькими способами - умерла так умерла. Как нагулилось - я в принципе всё делал правильно за некоторым исключением, нужно было после получения некорректной работы погуглить ещё, а не тыкать проводки. В этой теме на официальном форуме по ардуинке есть и полученные мною симптомы и решение проблемы. Наверное буду всё-таки побеждать тиньку ;) Но уже придется заказать новую - благо стоит копейки. 1 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted June 9, 2017 Author Share Posted June 9, 2017 (edited) Прочел книгу про кватернионы и трехмерную геометрию, начал заново копать ориентацию в пространстве с помощью MPU-9250. Набаловавшись до "не могу" со всякими фильтрами Маджвика, Махони и Калмана и так и не получив внятную картинку в Blender - пошел по пути наименьшего сопротивления. А если быть точным решил попробовать DMP (digital motion process), который по-умолчанию есть в датчике. Результат на видео. Если я правильно понимаю, то для более точного позиционирования (а кубик гуляет по оси Z где то секунд 10, в самом начале), нужно дополнительно забирать данные магнитометра и корректировать полученный из DMP кватернион. Edited June 9, 2017 by kharlashkin 1 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted June 12, 2017 Author Share Posted June 12, 2017 Чет, не могу считать данные магнитометра. Код для получения кватерниона с помощью DMP брал отсюда (улыбнуло размещение сайта - kr). Относительно управления платформой кватернионами, нашел интересную статью - "Применение кватернионов в задачах наведения антенной системы ретранслятора связи на беспилотном летательном аппарате". Решается задача подобная моей для антенны с 3-мя степенями свободы, а чтобы получить 6 степеней нужно наверное будет использовать бикватернионы. Кому интересно статья во вложении. primenenie-kvaternionov-v-zadachah-navedeniya-antennoy-sistemy-retranslyatora-svyazi-na-bespilotnom-letatelnom-apparate.pdf @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted June 20, 2017 Author Share Posted June 20, 2017 (edited) Сегодня получилось уделить немного времени подключению ардуинки по Bluetooth. Платка где-то месяц уже у меня не все никак руки не доходили. Итак, платка вот такая HC-06 (фото не мое): Перво-наперво нужно настроить модуль для работы, думаю понятно что скорость 9600 б/с будет маловата. Инструкций в интернетах несколько, попробовав некоторые - привожу что и как получилось у меня. В качестве транслятора команд для настройки модуля я использовал саму ардуинку. Собственно код, который позволяет обмен данными между ПК и модулем: #include <SoftwareSerial.h> #include <Time.h> int gLedPin = 13; int gRxPin = 10; // Pin-ы подключения модуля int gTxPin = 11; SoftwareSerial BTSerial(gRxPin, gTxPin); void setup() { // Настраиваем скорости обмена от ПК в ардуину и в модуль BTSerial.begin(9600); Serial.begin(38400); delay(500); } void loop() { if (BTSerial.available()) { Serial.write(BTSerial.read()); } if (Serial.available()) { BTSerial.write(Serial.read()); } } Для работы с модулем корректно завелась программка терминала HMComAssistant (архив приложил). Остальные могли только одну команду "AT", т.е. не поменять ни скорость, ни пин-код, ни посмотреть версию прошивки не смогли. Так же прилагаю документ с AT-командами. P.S. Собственно я уже попробовал крутить кубик в Blender через беспроводной интерфейс ;) Жду в течении 7/10 дней портативный аккумулятор и буду делать более корректное видео кручения автономного кубика (привет Portal/Portal2) + причесывать код. HMComAssistant.7z AT_HC05.pdf Edited June 20, 2017 by kharlashkin @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted June 26, 2017 Author Share Posted June 26, 2017 (edited) умерла так умерла. Приехала новая "тинька". Как не странно, всё завелось "с пол пинка". 'Код Digispark' #include "SoftSerial.h" #include "TinyPinChange.h" SoftSerial mySerial(3, 4); #define ControlSimistor 1 // Выход на симистор, физический порт P1 #define ControlZero 2 // Вход контроля перехода через 0, физический порт P2 volatile byte dimming = 0; // Начальное значение мощности void setup() { mySerial.begin(9600); pinMode(ControlSimistor, OUTPUT); // Включаем работу выхода на симистор pinMode(ControlZero, INPUT); // Переключаем контроль перехода через 0 на выход digitalWrite(ControlZero, HIGH); // Активируем контроль перехода через 0 attachInterrupt(0, zero, RISING); // Внешнее прерывание контроля перехода через ноль } void zero() // Если есть переход через 0 { if (dimming >= 255) // Если задано максимальное значение { digitalWrite(ControlSimistor, HIGH); // Тиристор постоянно открыт } else if (dimming <= 10) // Если минимум { digitalWrite(ControlSimistor, LOW); // Тиристор закрыт } else if (dimming > 10 && dimming < 255) // Если не минимум и не максимум { digitalWrite(ControlSimistor, LOW); // Сначала закрываем delayMicroseconds((5100 - dimming * 20)); // Ждем digitalWrite(ControlSimistor, HIGH); // Открываем тиристор } } void loop() { if (mySerial.available()) { dimming = mySerial.read(); } } 'Код Arduino' #include "SoftwareSerial.h" SoftwareSerial mySerial(10, 11); // Задаем программный порт на 10 и 11 портах volatile byte dimming = 0; // Начальное значение мощности void setup() { Serial.begin(57600); // Включаем порт с ПК mySerial.begin(9600); // Включаем порт с Attiny85 } void loop() { if (Serial.available()) // Если порт открыт { dimming = Serial.parseInt(); // Считываем данные и находим в них целое число mySerial.write(dimming); // Отправляем значение мощности в Attiny85 } } Есть багофича - значения менее 17 тинька отрабатывает но вентилятор не крутится. Думаю переделать на более вменяемые значения мощности :) P.S. Думаю что первоначальная платка имела брак - потому как новая завелась под Ubuntu на рабочем ноуте без "бубна";) Edited June 26, 2017 by kharlashkin 1 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted August 11, 2017 Author Share Posted August 11, 2017 (edited) После отпуска по доставал свои игрушки, взялся с новыми силами за положения в пространстве датчика MPU-9250. Чет, не могу считать данные магнитометра. Получилось заставить DMP обрабатывать данные от магнитометра, дополнительно включил математику в обработку кватерниона от DMP по этой статье. В принципе получилось очень даже ничего, особенно учитывая что данные от магнитометра без калибровки. Есть лишь небольшое подергивание кубика в блендер, но зато практически полностью пропал дрифт. Видео чуть позже добавлю. Залил проект на github. Имхо, будет неплохо наложить фильтр Калмана на данные от магнетометра, повысить точность позиционирования например на 4 знака после запятой (сейчас, как видно 2). test.7z Edited August 13, 2017 by kharlashkin 2 @ Quote Link to comment Short link Share on other sites More sharing options...
Pavel3333 Posted August 13, 2017 Share Posted August 13, 2017 класс. 1 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted August 14, 2017 Author Share Posted August 14, 2017 класс. Спасибо Вам, Павел, за поддержку. Очень часто, именно вот таких простых слов от окружающих в отношении того, что ты делаешь - не хватает ;) 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Pavel3333 Posted August 14, 2017 Share Posted August 14, 2017 всегда рад, проект сложный, по крайней мере для меня. продолжайте в том же духе, авось получится какая-нибудь полезная диковинка. @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted August 14, 2017 Author Share Posted August 14, 2017 всегда рад, проект сложный, по крайней мере для меня. продолжайте в том же духе, авось получится какая-нибудь полезная диковинка. Думаю что настоящему программисту, а не поделке в моем лице, работы было бы на пару дней. Мне больше для души нравится копошиться в этом всём, математику пришлось подтянуть для понимания общего процесса. Ну уже с Вами обсуждалось какую диковинку :) Сейчас у меня лежит 3 датчика 9250, 3 платки Arduino Pro Mini + едет батарейка с платкой именно для продолжение проекта. Думаю попробовать сделать подобие отслеживания руки (плечо, предплечье и кисть). Ломал на дня голову с корпусами - решил использовать обычные двойные телефонные розетки, сразу вопрос с соединениями отпадёт - все таки разъемные с нормальным проводом это плюс ;) Тестировал дома код для MPU-9250 чет не такой стабильный оказался на столе, но выявилась проблема с домашней экспериментальной Uno - рандомно ложится передача данных. Пробовал на ноуте/ПК под разными ОС - идет передача данных 2-5-10-20 сек и потом всё замирает. Хотя после повторной инициализации соединения - все работает нормально. На работе где экспериментирую с Nano - все более-менее стабильно. 2 @ Quote Link to comment Short link Share on other sites More sharing options...
kharlashkin Posted August 15, 2017 Author Share Posted August 15, 2017 Гы. Создал в MakeHuman персонажа со скелетом, набросал скриптик для забора данных из Arduino и отправки кватернионов для положения кости головы персонажа. Весело получилось - крутить на usb-шнуре коробок с датчиком и ардуинкой и смотреть как голова сходит с ума. 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Pavel3333 Posted August 20, 2017 Share Posted August 20, 2017 @kharlashkin, красава!!! это то, что я хотел! весело получилось. еще бы физ. движок подключить с мультиплАером, классно бы было. 1 @ Quote Link to comment Short link Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.