Страницы

Поиск по вопросам

Показаны сообщения с ярлыком arduino. Показать все сообщения
Показаны сообщения с ярлыком arduino. Показать все сообщения

четверг, 13 февраля 2020 г.

Как ловить данные из com-порта и использовать в своих программах?

#arduino #com_порт


Возникла необходимость получать данные с Arduino, к ней подключен RC522 и в мониторе
порта выводится 1 строка чисел, мне хочется чтобы при считывании эта строка 
1)выводилась на экран
2)записывалась в текстовик 
3)Отправлялась на сервер
Такое возможно?
    


Ответы

Ответ 1



Есть два варианта либо искать в интернете программу, которая слушает СОМ-порт и как-то пересылать на сервер, либо писать программу самому. Во втором случае нужно определится с языком программирования. Например, если вы решите использовать C#, то здесь есть фрагмент кода, который можно незначительно изменить и получить желаемый вами результат. Обновление чтение моментальное. Данные пришли данные отобразились. Можете изменять таймауты получения и отправки вручную (это миллисекунды). Программа видит все что пришло в ком порт, неважно какой источник данных. Единственное что замечу в вашем случае возможно придется использовать не ReadExisting, a ReadByte. Зависит от формата передаваемых данных, нужно смотреть. Если будут вопросы создавайте новый вопрос, поможем.

Ответ 2



Возможно, вам окажется не бесполезной моя статья об этом. Host-клиент Arduino на C (Linux)

понедельник, 10 февраля 2020 г.

В переменной типа long не помещается выражение 300*300

#c #arduino #преобразование


В языке ардуино, если писать 

long A = 90000;
Serial.println(A);


то все правильно работает, но если писать

long A = 300*300;
Serial.println(A);


то выводит 24464. И даже если писать 

Serial.println(300*300);


то результат тот же. В чем может быть проблема?
    


Ответы

Ответ 1



Похоже, что выражение long A = 300*300; ^^^^^^^^ вычисляется, как имеющее тип int, и объект типа int не может вместить в себя результирующее значение. Запишите следующим образом long A = ( long )300*300; или long A = 300l*300l; Что касается данной инициализации long A = 90000; то для целочисленного литерала компилятор определяет тот целочисленный тип, который может вместить в себя данное значение. Согласно стандарту C (6.4.4.1 Integer constants) 5 The type of an integer constant is the first of the corresponding list in which its value can be represented И далее в таблице указывается, что когда литерал не имеет суффикса, то последовательно подбирается тип литерала в порядке int, long int, long long int.

воскресенье, 26 января 2020 г.

Как передать информацию с помощью NFC?

#android #nfc #arduino


Добрый день.
Хочу поднять вот какую проблему. Хочу передать информацию из телефона (андроид) в
ардуино посредством nfc-интерфейса, а именно используя специальный модуль rc522. Вот
опорная статья http://robocraft.ru/blog/3004.html
Если с ардуино все более-менее ясно, то вот с андроид не понятно, как именно нужно
передавать информацию (например, какие-нибудь символы), чтобы ардуино воспринимала
телефон как карту?    


Ответы

Ответ 1



Один из режимов работы мобильного устройства с антенной для NFC - эмуляция NFC карты (Card emulation mode). Здесь общее описание. Здесь - более подробное.

четверг, 23 января 2020 г.

Чтение данных с arduino uno через COM порт

#c_sharp #arduino


Доброе время суток! Возникла проблема: код на arduino нормально работает, во встроенном
мониторе порта данные правильно отображаются. Но в приложении на C#, особенно очень
часто в самом начале приходит непонятных мусор вместо значений.
Типичные значения во встроенном мониторе:


  145
  
  0
  
  145
  
  0


Значения в программе на C#:


  SSH(??j - откуда берутся эти строки?
  
  145
  
  143
  
  ??j


Код программы

public partial class MainWindow : Window
{
    SerialPort sp = new SerialPort("COM3", 115200, Parity.None, 8, StopBits.One);

    public MainWindow()
    {
        InitializeComponent();

        sp.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);
        sp.Open();
    }

    private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        Dispatcher.BeginInvoke(new Action(delegate()
            {
                this.console.Text += sp.ReadExisting();
            }));

    }

    private void ReadPort(object source, ElapsedEventArgs e)
    {

    }

    private void readButton_Click(object sender, RoutedEventArgs e)
    {

    }
}


}
    


Ответы

Ответ 1



Много работал с компортом и ардуиной. Тагер(для лезертага) делал и прочее. Как я понял мусор в компорте - это вообще норма. Собственно для этого и существуют различные протоколы передачи данных. В простейшем случае, ты должен сначала слать идентификатор начала данных. Это может быть что угодно. Допустим [StartData]. Следом шлешь данные. А после идентификатор конца данных. [StopData]. Не плохо бы еще прикрутить контрольную сумму(гугли по CRC) и длину данных. Тогда в с# ты будешь сначала искать в потоке компорта идентификатор начала пакета. Потом читать ответ до идентификатора конца пакета. Реализовывать чтение можно по-байтово. Считываем байт - если равен '[', то читаем дальше, если следующий 'S' то продолжаем. Нет - отбрасываем, начинаем сначала.

пятница, 10 января 2020 г.

Тахометр на arduino

#arduino


Добрый день. На первичном валу катера приклеил 2 магнита, установил датчик холла.
Данные с датчика холла поступают на Arduino due. Код выглядит следующим образом:

#include 

const int RPM_PIN=3;
volatile int rpm                = 0;    // Тахометр
volatile int rpm_tik            = 0;    // Импуслы тахометра

void rpm_count(){
  rpm_tik++;
}

void SensorData(){
  rpm = rpm_tik;
  rpm_tik = 0;
}

void setup(){
   Serial.begin(9600);
   pinMode(RPM_PIN,INPUT);
   attachInterrupt(RPM_PIN,  rpm_count,  RISING);
   Timer3.attachInterrupt(SensorData);
   Timer3.start(1000000);
}

void loop(){
    Serial.println(rpm/2*60);
    delay(500);
}


на малых оборотах двигателя все соответствует истине. Но при увеличении оборотов
показания начинают завышаться. Так при оборотах 5000-5500 (примерное значение, ибо
прибор аналоговый) - получаю значение 6600 и выше. В чем может быть проблема?
    


Ответы

Ответ 1



Заменил вызов прерывания на: attachInterrupt(digitalPinToInterrupt(RPM_PIN), rpm_count, RISING); вместо attachInterrupt(RPM_PIN, rpm_count, RISING); Все заработало правильно.

Ответ 2



Слишком много вариантов, начиная от программных глюков (хотя на это не похоже) и заканчивая наводками от системы зажигания. Берите осциллограф, изучайте форму входного сигнала. Тут хватит и осциллографа из звуковой карты. Берите также генератор и давайте вашему тахометру тестовые сигналы.

четверг, 9 января 2020 г.

Как узнать сколько денег на счете сим карты в gsm модеме, Arduino?

#arduino


Скажите, пожалуйста, как в arduino вы можете узнать, сколько денег на SIM-карте в
gsm модеме. Я знаю команду AT ("AT+CUSD=1,\"#100#\""), но я не знаю, как записать ответ
на переменную. Помогите сделать это.
    


Ответы

Ответ 1



вопрос был решён довольно давно.. но вдруг кому-то пригодится char inputGsmFullArr[200] = {0}; //массив для хранения всей смс short int indxGsm = 0; // счетчик символов для буфера String inputGsmFullStr = ""; //входящая строка с gsm модема - полная bool flagGsmActive = false; char ch = NULL; void loop() { while (gprsSerial.available()) { delay(1); flagGsmActive = true; byte c = gprsSerial.read(); inputGsmFullArr[indxGsm++] = c; logger.LogPrintBytes(c); } if (!gprsSerial.available() && flagGsmActive) { for (int i = 0; i < indxGsm; i++) { inputGsmFullStr += inputGsmFullArr[i]; } ReadGsmStr(inputGsmFullStr); ClearBufferArray(inputGsmFullArr, indxGsm); indxGsm = 0; flagGsmActive = false; Serial.flush(); gprsSerial.flush(); } } void ClearBufferArray(char *array, short int sizeBuf) // function to clear buffer array { for (byte i = 0; i < sizeBuf; i++) { array[i] = NULL; } } //Обработка смс приемника-передатчика //---------------------------------- boolean isStringMessage = false; //Флаг, что данные с GSM содержат текстовое сообщение String lineFullStr = ""; // Входная строка построчно из inputGsmFullStr String currNumTmp = ""; //---------------------------------- //--------------------------------------------------------------------------------------------------// void ReadGsmStr(String fullGmsStr) { //Очистили подстроку главной строки lineFullStr = ""; //Читаем посимвольно нашу полную СМС и выдергиваем оттуда подстроки //А вид она имеет следующий \r\n +CMT: "+79999999999","NAME","16/01/28,00:36:38+24" \r\n // 1234567890 \n // 1234567890 \r\n for (int i = 0; i < fullGmsStr.length(); i++) { //Если находим символ возврата каретки if (fullGmsStr.charAt(i) == '\r') { // если это продолжение полной смс - само тело без заголовка - 1234567890 \n - то обрабатываем то что внутри (команды) if (isStringMessage) { lineFullStr.toUpperCase(); CheckGsmSubString(lineFullStr); isStringMessage = false; } else { CheckGsmSubString(lineFullStr); } lineFullStr = ""; } else if ('\n' != fullGmsStr.charAt(i)) { lineFullStr += fullGmsStr.charAt(i); } else if ('\n' == fullGmsStr.charAt(i)) { lineFullStr += '\n'; } } inputGsmFullStr = ""; //Очищаем то что пришло с GSM } //--------------------------------------------------------------------------------------------------// void CheckGsmSubString(String gsmSubStr) { // если это текстовое сообщение if (StringContains(gsmSubStr, "+CMT")) { //Парсим смс } // если это звонок else if (StringContains(gsmSubStr, "+CLIP")) { //Парсим звонок } // этот блок отлавливает ответ на запрос баланса и отправляет его смской else if (StringContains(gsmSubStr, "+CUSD")) { IsRequestBalanceFromGsm(gsmSubStr); } //---------------------КОМАНДЫ---------------------------- // делаем запрос баланса (мтс), ответ ловится +CUSD else if (StringContains(gsmSubStr, "BAL")) { gprsSerial.println("ATD#100#"); } } //--------------------------------------------------------------------------------------------------// // запрос баланса и отправляет его смской +CUSD void IsRequestBalanceFromGsm(String str) { str = str.substring(str.indexOf("Balance"), str.indexOf("r")); delay(1500); str += " is your balance of number " + currentNumber; SendSms("ТУТ НОМЕР НА КОТОРЫЙ ОТПРАВЛЯТЬ ОТВЕТ", str); } //--------------------------------------------------------------------------------------------------// const char q = (char)34; // символ " const char r = (char)13; // символ возврата каретки (Enter) const char z = (char)26; // передача ^Z // Функция отправки смс void SendSms(String number, String text) { logger.LogPrintlnStr("SEND SMS FUNC RETURN: "); logger.LogPrintlnStr("NUMBER: " + number + "\nTEXT: " + text); gprsSerial.println("AT+CMGD=4"); //удалить все сообщения на сим карте delay(1500); gprsSerial.print("AT+CMGS="); // send the SMS the number gprsSerial.print(q); // передача в порт символа " gprsSerial.print(number); // передача номера телефона gprsSerial.print(q); // передача в порт символа " gprsSerial.print(r); delay(1500); gprsSerial.println(text); // передача текста сообщения delay(500); gprsSerial.print(z); // передача ^Z gprsSerial.print(r); // передача Enter }

суббота, 21 декабря 2019 г.

Оставить только целые от десятичной дроби

#arduino #float


Имеются данные с датчика температуры (arduino + ds18b20 + библиотека dallas temp),

float temp = 26.23;


Нужно записать в переменную только целую часть, то есть 26, выводить умею: Serial.println
(temp,0); а вот в переменную записать не могу.
    


Ответы

Ответ 1



Float это сразу почти 1кб места в скетче + еще 4 байта на каждую переменную. Не надо так... Обычная операция *100 при получении данных и /%100 при выводе их на экран, решает вашу проблему

Ответ 2



Сделал след. образом с помощью cast: Ввел дополнительную переменную int inttemp; затем конвертировал переменную temp с float значением (26.23) в integer inttemp = (int)temp; и на выходе получил 26

Ответ 3



Выдача гугл http://arduino.ru/forum/programmirovanie/rabota-s-float "пешком" нужное преобразование можно сделать следующим образом: float v; long V; ... v=13.67; V=round(v*10); V/10 // целая часть числа V%10 // дробная часть числа (1 позиция) А еще легче просто не доводить до флоат. в авр нет флоата как такового и в 99% случаев можно обойтись и без него.

Ответ 4



я бы сделал вот так int temp = (int)26.23; Serial.println (temp,0);

понедельник, 9 декабря 2019 г.

где найти заземление

#микроконтроллеры #arduino #avr


есть AVR - ATmega32, и есть плата, в которой она уютно сидит. плата наподобие Arduino.

на плате есть удобные выводы по бокам для всех портов (A, B, C, D), и даже Vcc, а
вот GND вытащить забыли. и сейчас, чтобы просто замерить напряжение, мне нужно вставать
на ногу самого контроллера, а ещё и держать там щуп, что совсем неудобно. а недавно
появилась необходимость подключить диоды на беспаечную плату, а замли то нет.

предположим, что я вообще не знаю электроники.

как мне провести землю/ноль/-/GND на беспаечную/монтажную плату?

нужно для светодиодов и датчика температуры.
не припаиваться же к ноге контроллера.


    


Ответы

Ответ 1



Там есть разъем ISP. У него 4 пина - это GND.

Ответ 2



распиновка интерфейсов ISP и JTAG. вывел землю из десятого пина, хотя второй тоже работает как ноль. оффтоп: спасибо всем участникам обсуждения.

среда, 4 декабря 2019 г.

В чем разница между Vcc, Vdd, Vee и Vss

#arduino #электроника #внешние_устройства


Попадалось множество принципиальных электрических схем, на устройствах, подключаемых
к компьютеру, где Vcc и Vdd взаимозаменяемы.


Знаю, что Vcc и Vdd используются для положительного напряжения, а Vss и Vee для обозначения
общей линии (земли), но в чем разница между каждыми из двух вариантов в парах?
Означают ли знаки C, D, S и E что-либо?


И в дополнение: почему Vdd а не просто Vd ?
    


Ответы

Ответ 1



Vcc, Vee, Vdd, Vss - откуда такие обозначения? Обозначения цепей питания проистекают из области анализа схем на транзисторах, где, обычно, рассматривается схема с транзистором и резисторами подключенными к нему. Напряжение (относительно земли) на коллекторе (collector), эмиттере (emitter) и базе (base) обозначают Vc, Ve и Vb. Резисторы подключенные к выводам транзистора обозначим Rc, Re и Rb. Напряжение на дальних (от транзистора) выводах резисторов часто обозначают Vcc, Vee и Vbb. На практике, например для NPN транзистора включенного по схеме с общим эмиттером, Vcc соответствуют плюсу, а Vee минусу источника питания. Соответственно для PNP транзисторов будет наоборот. Аналогичные рассуждения для полевых транзисторов N-типа и схемы с общим истоком дают объяснение обозначений Vdd и Vss (D — drain, сток; S — source, исток): Vdd — плюс, Vss — минус. Обозначения напряжений на выводах вакуумных ламп могут быть следующие: Vp (plate, anode), Vk (cathode, именно K, не C), Vg (grid, сетка). Как написано выше, Vcc и Vee используются для схем на биполярных транзисторах (Vcc - плюс, Vee — минус), а Vdd и Vss для схем на полевых транзисторах (Vdd - плюс, Vss — минус). Такое обозначение не совсем корректно, так как микросхемы состоят из комплементарных пар транзисторов. Например, у КМОП микросхем, плюс подключен к P-FET истокам, а минус к N-FET истокам. Тем не менее, это традиционное устоявшее обозначение для цепей питания независимо от типа проводимости используемых транзисторов. Для схем с двух полярным питанием Vcc и Vdd могут интерпретироваться как наибольшее положительное, а Vee и Vss как самое отрицательное напряжение в схеме относительно земли. Для микросхем питающихся от одного или нескольких источников одной полярности минус часто обозначают GND (земля). Земля может быть разной, например, сигнальная, соединение с корпусом, заземление. Не знаю разрешено ли указывать сторонние ресурсы, но мне кажется будет нечестным умалчивать автора. РадиоКот

пятница, 12 июля 2019 г.

Чтение данных с com порта к которому подключена Arduino

Как считывать строки с Arduino так чтобы последние символов строки не обрезались ? Может дайте ссылки на литературу как это сделать !! Использую javafx+jssc.
Код :
@FXML private void handleButtonAction(ActionEvent event) { System.out.println("You clicked me!"); label.setText("Hello World!"); SerialPort serialPort = new SerialPort("COM5"); try { serialPort.openPort();//Open serial port serialPort.setParams(9600, 8, 1, 0);//Set params. byte[] buffer = serialPort.readBytes(10);//Read 10 bytes from serial port serialPort.closePort();//Close serial port String str = new String(buffer, StandardCharsets.UTF_8); System.out.println(str); } catch (SerialPortException ex) { System.out.println(ex); }
}
Должно быть :
1.791 1.791 1.425
1.325 Есть :
1.791 1.7 1.4 2 5 1. 3 2 5
Пробывал делать так :
SerialPort serialPort = new SerialPort("COM12"); try { serialPort.openPort();//Open serial port serialPort.setParams(9600, 8, 1, 0);//Set params. byte[] but = serialPort.readBytes(3);//Read 10 bytes from serial port serialPort.closePort();//Close serial port
ByteBuffer buffer = ByteBuffer.wrap(but); buffer.get(); while(buffer.getLong()==3) { System.out.println(buffer); buffer.clear(); } } catch (SerialPortException ex) { System.out.println(ex); }
}

Получил :
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774) at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Node.fireEvent(Node.java:8413) at javafx.scene.control.Button.fire(Button.java:185) at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$MouseHandler.process(Scene.java:3757) at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431) at com.sun.glass.ui.View.handleMouseEvent(View.java:555) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275) at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769) ... 48 more Caused by: java.nio.BufferUnderflowException at java.nio.Buffer.nextGetIndex(Buffer.java:506) at java.nio.HeapByteBuffer.getLong(HeapByteBuffer.java:412) at jssctest.FXMLDocumentController.handleButtonAction(FXMLDocumentController.java:41) ... 58 more


Ответ

Порт не обязан отдавать всё, что посылается другой стороной, одной пачкой.
Прочитайте то, что есть, добавьте к буферу-накопителю. Когда в накопителе соберётся полная посылка (обычно протокол обмена предусматривает наличие стоп-символов, например - перевода строки), обработайте её.
При возможности используйте асинхронный режим (событие порта, возникающее при получении данных)

суббота, 27 апреля 2019 г.

В переменной типа long не помещается выражение 300*300

В языке ардуино, если писать
long A = 90000; Serial.println(A);
то все правильно работает, но если писать
long A = 300*300; Serial.println(A);
то выводит 24464. И даже если писать
Serial.println(300*300);
то результат тот же. В чем может быть проблема?


Ответ

Похоже, что выражение
long A = 300*300; ^^^^^^^^
вычисляется, как имеющее тип int, и объект типа int не может вместить в себя результирующее значение.
Запишите следующим образом
long A = ( long )300*300;
или
long A = 300l*300l;
Что касается данной инициализации
long A = 90000;
то для целочисленного литерала компилятор определяет тот целочисленный тип, который может вместить в себя данное значение.
Согласно стандарту C (6.4.4.1 Integer constants)
5 The type of an integer constant is the first of the corresponding list in which its value can be represented
И далее в таблице указывается, что когда литерал не имеет суффикса, то последовательно подбирается тип литерала в порядке int, long int, long long int

суббота, 16 марта 2019 г.

Чтение данных с arduino uno через COM порт

Доброе время суток! Возникла проблема: код на arduino нормально работает, во встроенном мониторе порта данные правильно отображаются. Но в приложении на C#, особенно очень часто в самом начале приходит непонятных мусор вместо значений. Типичные значения во встроенном мониторе:
145 0 145 0
Значения в программе на C#:
SSH(??j - откуда берутся эти строки? 145 143 ??j
Код программы
public partial class MainWindow : Window { SerialPort sp = new SerialPort("COM3", 115200, Parity.None, 8, StopBits.One);
public MainWindow() { InitializeComponent();
sp.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived); sp.Open(); }
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e) { Dispatcher.BeginInvoke(new Action(delegate() { this.console.Text += sp.ReadExisting(); }));
}
private void ReadPort(object source, ElapsedEventArgs e) {
}
private void readButton_Click(object sender, RoutedEventArgs e) {
} }
}


Ответ

Много работал с компортом и ардуиной. Тагер(для лезертага) делал и прочее. Как я понял мусор в компорте - это вообще норма. Собственно для этого и существуют различные протоколы передачи данных. В простейшем случае, ты должен сначала слать идентификатор начала данных. Это может быть что угодно. Допустим [StartData]. Следом шлешь данные. А после идентификатор конца данных. [StopData]. Не плохо бы еще прикрутить контрольную сумму(гугли по CRC) и длину данных. Тогда в с# ты будешь сначала искать в потоке компорта идентификатор начала пакета. Потом читать ответ до идентификатора конца пакета.
Реализовывать чтение можно по-байтово. Считываем байт - если равен '[', то читаем дальше, если следующий 'S' то продолжаем. Нет - отбрасываем, начинаем сначала.

вторник, 5 марта 2019 г.

Как узнать сколько денег на счете сим карты в gsm модеме, Arduino?

Скажите, пожалуйста, как в arduino вы можете узнать, сколько денег на SIM-карте в gsm модеме. Я знаю команду AT ("AT+CUSD=1,\"#100#\""), но я не знаю, как записать ответ на переменную. Помогите сделать это.


Ответ

вопрос был решён довольно давно.. но вдруг кому-то пригодится
char inputGsmFullArr[200] = {0}; //массив для хранения всей смс short int indxGsm = 0; // счетчик символов для буфера String inputGsmFullStr = ""; //входящая строка с gsm модема - полная bool flagGsmActive = false; char ch = NULL;
void loop() { while (gprsSerial.available()) { delay(1); flagGsmActive = true; byte c = gprsSerial.read(); inputGsmFullArr[indxGsm++] = c; logger.LogPrintBytes(c); } if (!gprsSerial.available() && flagGsmActive) { for (int i = 0; i < indxGsm; i++) { inputGsmFullStr += inputGsmFullArr[i]; } ReadGsmStr(inputGsmFullStr); ClearBufferArray(inputGsmFullArr, indxGsm); indxGsm = 0; flagGsmActive = false; Serial.flush(); gprsSerial.flush(); } }
void ClearBufferArray(char *array, short int sizeBuf) // function to clear buffer array { for (byte i = 0; i < sizeBuf; i++) { array[i] = NULL; } }
//Обработка смс приемника-передатчика //---------------------------------- boolean isStringMessage = false; //Флаг, что данные с GSM содержат текстовое сообщение String lineFullStr = ""; // Входная строка построчно из inputGsmFullStr String currNumTmp = ""; //---------------------------------- //--------------------------------------------------------------------------------------------------// void ReadGsmStr(String fullGmsStr) { //Очистили подстроку главной строки lineFullStr = ""; //Читаем посимвольно нашу полную СМС и выдергиваем оттуда подстроки //А вид она имеет следующий
+CMT: "+79999999999","NAME","16/01/28,00:36:38+24"
// 1234567890
// 1234567890
for (int i = 0; i < fullGmsStr.length(); i++) { //Если находим символ возврата каретки if (fullGmsStr.charAt(i) == '
') { // если это продолжение полной смс - само тело без заголовка - 1234567890
- то обрабатываем то что внутри (команды) if (isStringMessage) { lineFullStr.toUpperCase();
CheckGsmSubString(lineFullStr);
isStringMessage = false; } else { CheckGsmSubString(lineFullStr); } lineFullStr = ""; } else if ('
' != fullGmsStr.charAt(i)) { lineFullStr += fullGmsStr.charAt(i); } else if ('
' == fullGmsStr.charAt(i)) { lineFullStr += '
'; } } inputGsmFullStr = ""; //Очищаем то что пришло с GSM } //--------------------------------------------------------------------------------------------------// void CheckGsmSubString(String gsmSubStr) { // если это текстовое сообщение if (StringContains(gsmSubStr, "+CMT")) { //Парсим смс } // если это звонок else if (StringContains(gsmSubStr, "+CLIP")) { //Парсим звонок } // этот блок отлавливает ответ на запрос баланса и отправляет его смской else if (StringContains(gsmSubStr, "+CUSD")) { IsRequestBalanceFromGsm(gsmSubStr); }
//---------------------КОМАНДЫ---------------------------- // делаем запрос баланса (мтс), ответ ловится +CUSD else if (StringContains(gsmSubStr, "BAL")) { gprsSerial.println("ATD#100#"); } } //--------------------------------------------------------------------------------------------------//
// запрос баланса и отправляет его смской +CUSD void IsRequestBalanceFromGsm(String str) { str = str.substring(str.indexOf("Balance"), str.indexOf("r")); delay(1500); str += " is your balance of number " + currentNumber; SendSms("ТУТ НОМЕР НА КОТОРЫЙ ОТПРАВЛЯТЬ ОТВЕТ", str); } //--------------------------------------------------------------------------------------------------// const char q = (char)34; // символ " const char r = (char)13; // символ возврата каретки (Enter) const char z = (char)26; // передача ^Z // Функция отправки смс void SendSms(String number, String text) { logger.LogPrintlnStr("SEND SMS FUNC RETURN: "); logger.LogPrintlnStr("NUMBER: " + number + "
TEXT: " + text); gprsSerial.println("AT+CMGD=4"); //удалить все сообщения на сим карте delay(1500); gprsSerial.print("AT+CMGS="); // send the SMS the number gprsSerial.print(q); // передача в порт символа " gprsSerial.print(number); // передача номера телефона gprsSerial.print(q); // передача в порт символа " gprsSerial.print(r); delay(1500); gprsSerial.println(text); // передача текста сообщения delay(500); gprsSerial.print(z); // передача ^Z gprsSerial.print(r); // передача Enter }

пятница, 12 октября 2018 г.

На чем сделать систему автополива и открытия/закрытия теплицы?

В общем-то, задача, которая стоит передо мной, описана в заголовке, сейчас опишу, как вижу процесс: 1. Компьютер - на данный момент обычный, в идеале Arduino. 2. Электроклапан (для отключения/включения подачи воды). 3. Электропривод стекла (для открывания форточек теплицы), думаю взять простой автомобильный. 4. Аккумулятор - тут вообще не знаю, что взять под это дело, не знаю, подойдет ли автомобильный. 5. Как-то воткнуть в это дело gsm модуль (3g модем как вариант).
Ну вот, в общем-то и все, то есть схема работы отправили смс с одним кодом, вода полилась, с другим остановилась и т.д. Потом можно будет датчики температуры воткнуть и тому подобные приколюхи! Но вот хотелось бы получить инфу от опытных людей, как все это организовать. Заранее спасибо!


Ответ

Raspberry PI2 и Arduino +gsm модуль + powerRalayPad (если ток большой).
По простому- микрокомпьютер Rasperry Pi2 (он с ардуиной вяжется, есть много всяких примеров в открытом доступе), ваша ардуино (достаточно просто в части написания кода под нее). gsm модуль для ардуины тоже есть, и есть примеры работы с ним и работы по командам принятым. PowerRelyaPad не что иное как управление силывами реле. Если меня не подводит память, то это на случай работы с 220в. Допускаю что мои познания в части плат управления выходами несколько устарели, но помнится мне есть плата управления выходами т.е. по сути подача питания на ваши подъемники.
И еще сразу решите задачу актуации положения окна т.к. вероятность того что сломается ЭСП существует. Посмотрите в сторону герконов или чего-то подобного сигнализациям на окна.
Почему пока что лучше использовать ардуино - простота в написании и доступность как примеров, так и компонентов. То, что у вас получится в итоге будет прототипом, на основе которого вы сможете исполнить реализацию на более правильных, с точки зрения отказоустойчивости, компонентов.

четверг, 11 октября 2018 г.

В чем разница между Vcc, Vdd, Vee и Vss

Попадалось множество принципиальный электрических схем, на устройствах, подключаемых к компьютеру, где Vcc и Vdd взаимозаменяемы.
Знаю, что Vcc и Vdd используются для положительного напряжения, а Vss и Vee для обозначения общей линии (земли), но в чем разница между каждыми из двух вариантов в парах? Означают ли знаки C, D, S и E что-либо?
И в дополнение: почему Vdd а не просто Vd ?


Ответ

Vcc, Vee, Vdd, Vss - откуда такие обозначения?
Обозначения цепей питания проистекают из области анализа схем на транзисторах, где, обычно, рассматривается схема с транзистором и резисторами подключенными к нему. Напряжение (относительно земли) на коллекторе (collector), эмиттере (emitter) и базе (base) обозначают Vc, Ve и Vb. Резисторы подключенные к выводам транзистора обозначим Rc, Re и Rb. Напряжение на дальних (от транзистора) выводах резисторов часто обозначают Vcc, Vee и Vbb.
На практике, например для NPN транзистора включенного по схеме с общим эмиттером, Vcc соответствуют плюсу, а Vee минусу источника питания. Соответственно для PNP транзисторов будет наоборот. Аналогичные рассуждения для полевых транзисторов N-типа и схемы с общим истоком дают объяснение обозначений Vdd и Vss (D — drain, сток; S — source, исток): Vdd — плюс, Vss — минус.
Обозначения напряжений на выводах вакуумных ламп могут быть следующие: Vp (plate, anode), Vk (cathode, именно K, не C), Vg (grid, сетка).
Как написано выше, Vcc и Vee используются для схем на биполярных транзисторах (Vcc - плюс, Vee — минус), а Vdd и Vss для схем на полевых транзисторах (Vdd - плюс, Vss — минус). Такое обозначение не совсем корректно, так как микросхемы состоят из комплементарных пар транзисторов. Например, у КМОП микросхем, плюс подключен к P-FET истокам, а минус к N-FET истокам. Тем не менее, это традиционное устоявшее обозначение для цепей питания независимо от типа проводимости используемых транзисторов. Для схем с двух полярным питанием Vcc и Vdd могут интерпретироваться как наибольшее положительное, а Vee и Vss как самое отрицательное напряжение в схеме относительно земли.
Для микросхем питающихся от одного или нескольких источников одной полярности минус часто обозначают GND (земля). Земля может быть разной, например, сигнальная, соединение с корпусом, заземление.
Не знаю разрешено ли указывать сторонние ресурсы, но мне кажется будет нечестным умалчивать автора. РадиоКот