проблемы с кодированием
Я работаю над проектом электромагнитного двигателя, управляемого Arduino, который я нашел на Instructables. Мне удалось собрать воедино то, что, по моему мнению, представляет собой большую часть кода, но я получаю некоторые синтаксические ошибки, и мне интересно, могу ли я получить некоторую помощь? Вот код и ошибки.
// Включая библиотеки
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <math.h>
LiquidCrystal_I2C mydisplay(0x27,16,2);
// Определить контакты ввода/вывода
#define solenoidpin 9
#define potpin 1
#define ignitioninputpin 2
///#определить прерывание номер 3
#define isr_rpm(INT0_vect)
// Определение переменных
int previousstate;
byte buttonstate;
int counter1;
int start;
int finish;
int elapsed;
int RPM;
// Основная настройка
void setup(){
pinMode(ignitioninputpin,INPUT);
digitalWrite(ignitioninputpin,HIGH);
//// AttachInterrupt(3,isr_rpm, FALLING);
counter1=1;
mydisplay.init();
mydisplay.backlight();
mydisplay.setCursor(0,1);
mydisplay.print(" Soleniod Motor ");
previousstate=HIGH;
Serial.begin(19200);
buttonstate = digitalRead(ignitioninputpin);
}
// Основной цикл программы
void loop() {
buttonstate = digitalRead(ignitioninputpin);
Serial.println(buttonstate);
Serial.write("previousstate");
Serial.println(previousstate);
Serial.println(counter1);
float elapsed=start=finish;
float RPM= (6000/elapsed);
{
if (buttonstate==LOW && previousstate==HIGH && (counter1%2)==0){
digitalWrite(solenoidpin,HIGH);
}
if (buttonstate==HIGH && previousstate==LOW && (counter1%2)==0){
digitalWrite(solenoidpin,HIGH);
}
if (buttonstate==LOW && previousstate==HIGH && (counter1%2)==0){
digitalWrite(solenoidpin,LOW);
}
if ((counter1%2)==0){ for rpm calcs
finish=start;
start=millis();
}
if ((counter1%6)==0){
mydisplay.setCursor(0,0);
mydisplay.print(" RPM ");
mydisplay.print(RPM);
mydisplay.setCursor(0,1);
mydisplay.print(" Solenoid Motor ");
}
void ISR1();
buttonstate=LOW;
counter1=counter1+1;
previousstate=HIGH;
}
}
Сообщения об ошибках:
Размер двоичного скетча: 7594 байта (максимум 32 256 байт)
@Key Price, 👍-2
Обсуждение2 ответа
Добро пожаловать в Arduino.SE. Я не собираюсь переписывать за вас код, но из этого и других ответов и комментариев вы сможете подкорректировать код под себя из конструктивной критики.
Начнем с самого начала.
Вы определили interruptpinnumber
, но не используете его в функции attachInterrupt
, поскольку объявляете вывод прерывания 1 (цифровой вывод 3), а не 0 в качестве вывода прерывания. вызвать проблемы в вашем коде.
Далее, ваши временные переменные должны быть unsigned long
, поскольку функция millis()
вернет unsigned long. Также нет необходимости объявлять их изменчивыми, поскольку вы не используете их в процедуре ISR.
Что касается ISR, вы использовали arduino attachInterrupt() и использовали фактический ISR()
подпрограмма из библиотек AVR, также без включая это. В ISR вам нужно передать ему вектор, которого нет и который позже будет давать ошибки. Вам также не нужна процедура ISR, если вы использовали функцию Arduino. Вам необходимо убедиться, что то, что вы объявляете как подпрограмму (то есть isr_rpm
) в функции attachInterrupt()
, которая будет выполняться при возникновении прерывания, действительно существует.
Кроме того, при вычислении прошедшего
времени возникают некоторые базовые арифметические проблемы, например, если вы пытаетесь определить разницу.
Как отметил @Majko, и я тоже собирался это сделать, использование побитового AND, &
в ваших операторах if()
может не быть проблема, но лучше всего сейчас усвоить, что для сравнения следует использовать логическое И &&
.
Существует также избыточный оператор if
, который я оставлю вам, чтобы найти его, поскольку это ваш код, и вы сможете определить, полезен он или нет. Также вам необходимо следить за своими скобками, так как это тоже приведет к ошибкам, которые вы видите.
Изменить
Думаю, мне нужно уточнить некоторые моменты, так как я думаю, что вы еще больше запутались.
Что касается всей функции Arduino AttachInterrupt, isr_rpm()
должен быть функцией, а не определением, я думаю, это и послужило причиной
В ISR вам нужно передать вектор, которого там нет и который в дальнейшем будет давать ошибки. Вам также не нужна процедура ISR, если вы использовали функцию Arduino. Вам необходимо убедиться, что то, что вы объявляете как подпрограмму (то есть
isr_rpm
) в функцииattachInterrupt()
, которая будет выполняться при возникновении прерывания, действительно существует.
Этой функцией будет:
void isr_rpm(){
//код
}
Поскольку @Majko любезно оказал вам услугу и аннотировал ваш код, посмотрите на материалы, связанные с процедурой прерывания (и другие материалы), и сравните их с приведенным ниже руководством по avrfreaks и оригиналом. код, если он у вас есть, проблема заключалась в том, что у вас было слишком много фигурных скобок:
void ISR(){
buttonState = LOW;
counter1 = counter1 + 1;
previousState = HIGH;
}
}
должно быть:
ISR(INT0_vect){
buttonState = LOW;
counter1 = counter1 + 1;
previousState = HIGH;
}
Нет необходимости давать ISR собственное специальное имя, оно взято из более нового кода.
Учебное пособие AVRfreaks, касающееся прерываний и ISR, которое оно даст вам тоже объяснение по поводу нестабильных вещей.
Я не могу больше подчеркнуть этот момент, но просмотрите свой код, аннотированный Маженко, и посмотрите, где вы можете его исправить.
Огромное спасибо, ребята, мне удалось исправить около 90%, и я думаю, что мне достаточно всего лишь нескольких небольших скобок, отступов и тому подобного. выпив чашку кофе и прочитав еще несколько справочных материалов вместе со всеми вашими комментариями, я решил придерживаться фактического ISR(). Маженко, спасибо за упоминание фигурных скобок, это очень помогло, и RSM, я бы не смог пережить утро без кофе и вашего руководства. как только я выясню, как происходит форматирование этих сообщений, я выложу новый и улучшенный код., @Key Price
@KeyPrice - я уверен, что помог, но, возможно, мне следовало быть более точным в использовании ISR, поскольку я думаю, что это привело к совершенно новым проблемам с кодом. Я бы рассмотрел аннотированный код Маженко и сравнил бы его со своими заметками. Кроме того, если у вас есть исходный код, посмотрите на него, так как в основном в нем были некоторые ошибки форматирования, и ISR был бы в порядке, если бы вы поместили вектор в эти скобки. Принесите ей еще кофе и прочитайте ссылку ISR() в моем посте. Также попробуйте http://www.avrfreaks.net/forum/tut-newbies-guide-avr-interrupts?page=all. Это хороший учебник., @RSM
Хорошо, я поклялся, что не буду этого делать, но я переформатировал ваш последний код и собираюсь просмотреть его и аннотировать.
// Включая библиотеки
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <math.h> /// << ПОЧЕМУ?! Вы им не пользуетесь!
LiquidCrystal_I2C mydisplay(0x27, 16, 2);
// Определить контакты ввода/вывода
#define solenoidpin 9
#define potpin 1
#define ignitioninputpin 2
///#определить прерывание номер 3
#define isr_rpm(INT0_vect) /// << Чего это надеется достичь?
// Определение переменных
int previousstate;
byte buttonstate;
int counter1;
int start; ///
int finish; /// << Они должны быть беззнаковыми длинными
int elapsed;///
int RPM;
// Основная настройка
void setup() {
pinMode(ignitioninputpin, INPUT);
digitalWrite(ignitioninputpin, HIGH);
//// AttachInterrupt(3,isr_rpm, FALLING); /// << Это никогда не будет работать с тем #define, на который я указал...
counter1 = 1;
mydisplay.init();
mydisplay.backlight();
mydisplay.setCursor(0, 1);
mydisplay.print(" Soleniod Motor ");
previousstate = HIGH;
Serial.begin(19200);
buttonstate = digitalRead(ignitioninputpin);
}
// Основной цикл программы
void loop() {
buttonstate = digitalRead(ignitioninputpin);
Serial.println(buttonstate);
Serial.write("previousstate");
Serial.println(previousstate);
Serial.println(counter1);
float elapsed = start = finish; /// << Вы уже определили их как целые числа в глобальном
float RPM = (6000 / elapsed); /// << объем. Почему вы снова определяете их как числа с плавающей запятой?! Также,
/// << прошедшее = начало = окончание?!?! Я думаю, у вас есть = вместо -
{ /// << Зачем вы тут новый блок начинаете???
if (buttonstate == LOW && previousstate == HIGH && (counter1 % 2) == 0) { /// << counter1 % 2 очень неэффективен, поскольку счетчик counter1 подписан.
digitalWrite(solenoidpin, HIGH);
}
if (buttonstate == HIGH && previousstate == LOW && (counter1 % 2) == 0) { /// << предыдущее состояние никогда не меняется с ВЫСОКОГО — это НИКОГДА не запустится!
digitalWrite(solenoidpin, HIGH);
}
if (buttonstate == LOW && previousstate == HIGH && (counter1 % 2) == 0) { /// << Вы уже проверили это состояние выше с другим результатом. ПОЧЕМУ?!?!
digitalWrite(solenoidpin, LOW);
}
if ((counter1 % 2) == 0) {
for rpm calcs /// << Это даже не Си!!!
finish = start;
start = millis();
}
if ((counter1 % 6) == 0) {
mydisplay.setCursor(0, 0);
mydisplay.print(" RPM ");
mydisplay.print(RPM);
mydisplay.setCursor(0, 1);
mydisplay.print(" Solenoid Motor ");
}
void ISR1(); /// << Это прототип функции, а не ее определение.
buttonstate = LOW; /// << Я думаю, они должны быть внутри
counter1 = counter1 + 1; /// << функция под названием ISR1(), но это
previousstate = HIGH; /// << функция не была написана.
}
}
Вы пытаетесь возиться с написанием процедур обработки прерываний низкого уровня, не имея ни малейшего понятия, как работать с процедурами обработки прерываний низкого уровня. Вернитесь и прочитайте руководства о том, как выполнять внешние прерывания с помощью Arduino. Это очень-очень просто.
В вашей программе есть вещи, которые заставляют меня задуматься: «Что?!?!» и вещи, которых просто не хватает.
- Проблема стабильности кода прерываний, связанного с датчиком расхода
- ЖК-дисплей I2C отображает странные символы
- Экран LCD 16*02 I2C показывает только первый напечатанный символ
- 16/2 arduino I2C ЖК-дисплей не загорается?
- Отправка буквы за буквой на ЖК-дисплей, однако дисплей знает полную строку?
- Альтернатива LCD-дисплеям UART/I2C?
- Arduino использует задержку в I2C ReceiveEvent
- Датчики I2C не работают при подключении к LCD дисплею 20X04
Хорошей отправной точкой может быть: «isr_rpm» не был объявлен в этой области». Это должно быть поправимо. Затем .., @Russell McMahon
Еще одна вещь, которую вы можете рассмотреть, — это потерять лишние пробелы в именах включаемых файлов.
<[пробел]Wire.h[пробел]>
не то же самое, что<Wire.h>
, @MajenkoЕще одна вещь, на которую следует обратить внимание, — это правильно сбалансировать кронштейны. У тебя там, кажется, есть лишний. Исправьте отступы, и вы скоро это заметите., @Majenko
Еще одна вещь, которую я только что заметил: проверьте использование
&
в операторахif()
... Возможно, это не вызывает проблем, но это определенно плохой стиль программирования, поскольку&
означает не то, что я думаю, ты думаешь, что это значит., @Majenko@Majko Я также заметил использование
&
, есть еще несколько вещей, которые сделал OP, а также избыточный оператор if()., @RSM@RSM Да, в методологии программы есть множество недостатков. Включая использование (или неиспользование)
previousstate
и большое количество дорогостоящих операций с модулями... А еще эта строка:float elapsed = start = Finish;
... Я имею в виду... ну... Также локальные переменные (число оборотов в минуту и истекшее время) конфликтуют с глобальными переменными (целое число оборотов в минуту и истекшее время)...!, @Majenko@Маженко: модуль 6 может быть дорогим, но модуль 2 дешевым., @Edgar Bonet
@Маженко Я нашел время, чтобы написать ответ и указать на прошедшее уравнение. Но ФП справедливо заявил, что они новички в этом., @RSM
Не называйте функцию ISR(): это имя уже используется макросом., @Edgar Bonet
@EdgarBonet Если компилятор правильно оптимизирует, да. Лучше сделать это правильно, чем рассчитывать, что компилятор исправит это за вас., @Majenko
@Majko: Если вы не доверяете своему компилятору в таких тривиальных вещах, то пишите на ассемблере, а не на C., @Edgar Bonet
@EdgarBonet Я прав, не доверяя компилятору.
% 2
вызывает вызов__divmodhi4
, что вряд ли эффективно - уж точно не так эффективно, как простое выполнение& 1
. Одна из вещей, которую вы вскоре узнаете при изучении встроенного программирования, — это эффективное программирование, при котором вы можете угадать компилятор и сделать его лучше., @Majenko@Маженко: Какой компилятор вы используете? Я бы не стал использовать настолько тупой компилятор, чтобы вызывать
__divmodhi4
для% 2
, и предлагаю вам подумать о переходе на достойный компилятор., @Edgar Bonet@EdgarBonet Стандартный avr-gcc. Компилятор понятия не имеет, что такое %. Он просто знает, что для выполнения операции % ему необходимо вызвать функцию libc, которая выполняет эту операцию. Он не может этого знать, поскольку второй аргумент равен 2, поэтому лучше было бы использовать совершенно другой набор операций, поскольку он не знает, что делает %. Точно так же, как если вы вызываете «sin(0)», он не может знать, что было бы лучше заменить его на «0», поскольку он не знает, что делает sin(). Это просто функция, которой является весь %. Для компилятора это то же самое, что
%(counter1, 2)
, @MajenkoДавайте [продолжим обсуждение в чате](http://chat.stackexchange.com/rooms/25540/discussion-between-edgar-bonet-and-majko)., @Edgar Bonet
@KeyPrice Со времени вашего последнего редактирования вы допустили несколько фундаментальных ошибок в своей программе. В частности, с вашей функцией ISR1(). **Исправьте отступы, чтобы видеть, где находится ошибка. Хорошие отступы облегчают понимание программ. Вы не можете понять свою программу, потому что у вас очень сломанная верстка. Начните с исправления макета, и вы увидите свои ошибки как божий день. Если вы не можете исправить макет, воспользуйтесь автоформатером, чтобы сделать это за вас.**, @Majenko
Куда пропали сообщения об ошибках? Похоже, они были удалены редактированием №7. Остаётся только сообщение о статусе компиляции., @Greenonline