Помогите новичку дописать код.

Life23
Offline
Зарегистрирован: 10.08.2013

Помогите объеденить и дописать код.

Есть код для включения LED с помощью смс.

и отправка смс с кнопки.

но смс отправляеться только кагда нажать кнопку. а мне надо что бы отправлялось смс и когда отпустить кнопку. т.е. обратная связь для LED. Точнее вместо светодиода будет реле с дублирующими контактами. Надо знать с помощью смс включилось ли реле на самом деле. и оповещать если разомкнулись контакты. Даже если с Ардуины LED (реле) включено.

 

Код включения LED:

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(3, 2);
int greenPin = 4;
void setup()
{
    gprsSerial.begin(9600);
    pinMode(greenPin, OUTPUT);
    // Настраиваем приём сообщений с других устройств
    // Между командами даём время на их обработку
    gprsSerial.print("AT+CMGF=1\r");
    delay(300);
    gprsSerial.print("AT+IFC=1, 1\r");
    delay(300);
    gprsSerial.print("AT+CPBS=\"SM\"\r");
    delay(300);
    gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
    delay(500);
}
 
String currStr = "";
// Переменная принимает значение True, если текущая строка является сообщением
boolean isStringMessage = false;
 
void loop()
{
    if (!gprsSerial.available())
        return;
 
    char currSymb = gprsSerial.read();    
    if ('\r' == currSymb) {
        if (isStringMessage) {
            //если текущая строка - SMS-сообщение,
            //отреагируем на него соответствующим образом
            if (!currStr.compareTo("Green on")) {
                digitalWrite(greenPin, HIGH);
            } else if (!currStr.compareTo("Green off")) {
                digitalWrite(greenPin, LOW);
            }
            isStringMessage = false;
        } else {
            if (currStr.startsWith("+CMT")) {
                //если текущая строка начинается с "+CMT",
                //то следующая строка является сообщением
                isStringMessage = true;
            }
        }
        currStr = "";
    } else if ('\n' != currSymb) {
        currStr += String(currSymb);
    }
}

Код отправки смс по нажатию кнопки.

#include <SoftwareSerial.h>
 SoftwareSerial gprsSerial(7, 8);
 int btnPin = 12;
boolean prevBtn = LOW;
 void setup()
{
    gprsSerial.begin(9600);
    delay(500);
}
 void loop()
{
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
        //сразу после нажатия кнопки отправляем "тревожное" сообщение по заданному номеру
        sendTextMessage();
    }
    prevBtn = currBtn;
}
 
/*
 * Функция отправки SMS-сообщения
 */
void sendTextMessage() {
    // Устанавливает текстовый режим для SMS-сообщений
    gprsSerial.print("AT+CMGF=1\r");
    delay(100); // даём время на усваивание команды
    // Устанавливаем адресата: телефонный номер в международном формате
    gprsSerial.println("AT + CMGS = \"+79************\"");
    delay(100);
    // Пишем текст сообщения
    gprsSerial.println("ALARM!");
    delay(100);
    // Отправляем Ctrl+Z, обозначая, что сообщение готово
    gprsSerial.println((char)26);
}

 

P.S. Прозьба сильно не пинать.. Новичек в этом деле..

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Для получение развернутого ответа отправьте смс на короткий номер ХХХХХХ

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Написать какое железо было видно не сдуьба?

Life23
Offline
Зарегистрирован: 10.08.2013

Arduino Diecimila (Atmega168) + ICOMSAT 1.1 (Sim900)

Железо работает. сообщения отправляет при замыкании кнопки. и LEDом управляет при отправке сообщения. 

Но я не совсем понимаю как правильно объеденить код. 

что бы: отправил смс -> вкл.светодиод. нажал после этого кнопку(и удерживаешь) -> шилд отправил смс что кнопка нажата. Отпустил кнопку -> шилд отправил сообщение что кнопка отпущена. хотя светодиод все равно светиться.

Другими словами, что бы кнопка отправляла смс при нажатии или отпускании и при этом указывалось что произошло: "отпустилась" кнопка или "нажалась".

кнопка и управление светодиодом должны работать независимо.

я так понимаю кнопка должна быть на пине 2 или 3 (апаратное прерывание). и естественно на кнопке физическая защита от дребезга (емкость с резистором).

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Так и что именно вас останавливает? полное не понимание кода? Вы ждете что щас все бросятся писать за вас код? Особенно порадовала ЕМКОСТЬ С РЕЗИСТОРОМ .. ух ты прям.. (представил себе такой бидон ( ну емксоть же все таки) и там значит внутри бидона кто то сидит и сопротивляется)

step962
Offline
Зарегистрирован: 23.05.2011

В качестве первого шага попробуйте найти те три строки в ваших кодах, которые отвечают за отправку смс при нажатии кнопки.

Получится - делайте второй шаг: попытайтесь понять, как работает условие, выполнение которого приводит к отправке смс.

Пройдете оба этих шага - останется сущая ерунда: copy+paste+modify.

Life23
Offline
Зарегистрирован: 10.08.2013

to, Puhlyavi, я понимаю, что никто не броситься и не напишет за меня код! и таких как я тут полно. но все таки форум не зря открыт. надеялся что хоть ткнете теорией. 

по поводу бидона: что Вас так, простите, роздражает, что Вы именно о бидине начали говорить, а не о конденсаторе и резисторе?. почему Jeremy Blum'а никто так не коментировал по поводу емкости? Понятно, что он специалист в этом впросе. Но зачем новичков так "опускать"? 

to, Step962: спасибо, попробую - отпишусь.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Life23 пишет:

to, Puhlyavi, я понимаю, что никто не броситься и не напишет за меня код! и таких как я тут полно. но все таки форум не зря открыт. надеялся что хоть ткнете теорией. 

Давайте зайдем с начала, что именно вы сделали сами? соединили проводки как на картинке, скопировали 2 скеча с подробными коментариями в один пост... вы не умеете читать коментарии? проблема с понимаем заложеного в коментарии смысла?

Или теория которая вам требуется это список общих функций и примеры их применения?

Что еще я пропустил? 

Тут у нас товарищ бегает с примерами на автомобильную тематику...

Так вот ваша ситуация выглядит примерно так.. забегаете в гараж и кричите.. Мужики у меня вот есть двигатель, он рабочий 100 процентов и есть рама от машины, тоже вроде не ржавая.. так эт не заводится нифига, не подскажете почему?

и кто такой Джереми Блум и почему я о нем должен знать? И самое забавное, если вы себе равняете с ним, то почему задаете такие глупые вопросы?

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku

Меняете "кнопку" на "отправку смс/щелканье релёй" итд

leshak
Offline
Зарегистрирован: 29.09.2011

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

Ну вот давайте, тогда, вначале решите эту задачу (и в ее процессе лучше поймете скетч), а потом уже займетесь объединением.

Сможете второй скетч модифицировать таким образом, что-бы он:

1. На нажатие кнопки отсылал SMS "Button Pressed"
2. На отпускание кнопки отсылал SMS "Button Released"

Сможете?  Если нет - все равно попробуйте и покажите что получилось :)
 

Life23
Offline
Зарегистрирован: 10.08.2013

ну как то вот так у меня получилось(только вместо отправки мигаю два раза светиками для проверки на железе):

int btnPin = 2;
int flag=0;


void setup()   
 { 
    pinMode(7, OUTPUT); 
    pinMode(8, OUTPUT);
    pinMode(2, INPUT); 
  }  
 void loop()
  { 
    if (digitalRead(2)==HIGH&&flag==0)
    {
      Comand_high();
    }
     if (digitalRead(2)==LOW&&flag==1)
     {
      Comand_low();
    }
}
void Comand_high()
{
    digitalWrite(7, HIGH);
    delay(300);
    digitalWrite(7,LOW);
    delay(300);
    digitalWrite(7, HIGH);
    delay(300);
    digitalWrite(7, LOW);
    flag=1;
    }
void Comand_low()
{
    digitalWrite(8, HIGH);
    delay(300);
    digitalWrite(8,LOW);
    delay(300);
    digitalWrite(8, HIGH);
    delay(300);
    digitalWrite(8, LOW);
    flag=0;
}

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Life23 пишет:

ну как то вот так у меня получилось(только вместо отправки мигаю три раза светиками для проверки на железе):

- Хороший, молодец! ( дал кусочек шоколадки и погладил по голове)

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

Life23
Offline
Зарегистрирован: 10.08.2013

Умеете Вы, Puhlyaviy под...ть...

leshak
Offline
Зарегистрирован: 29.09.2011

Puhlyaviy пишет:

- Хороший, молодец! ( дал кусочек шоколадки и погладил по голове)

Остроумие - это хорошо. Только применять его нужно к месту и по делу. Иначе остроумие превращается в ослоумие. Человек делом занимается, учится/разбирается. А вы - мешаете.

Это как собака:  если лает на цыган лезущих через забор - хорошая охранная собака, если лает на весь белый свет и кусает гостей - это шавка истеричная.

Так что "фу!!!!! молчать!!! на место.."

2Life23:  я чуть-чуть позже прокоментирую/поправлю  ваш скетч.

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

leshak пишет:

Остроумие - это хорошо. Только применять его нужно к месту и по делу. Иначе остроумие превращается в ослоумие. Человек делом занимается, учится/разбирается. А вы - мешаете.

Это как собака:  если лает на цыган лезущих через забор - хорошая охранная собака, если лает на весь белый свет и кусает гостей - это шавка истеричная.

Так что "фу!!!!! молчать!!! на место.."

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

А на собак вы здря  волну гоните, они могут в конце обидется и уйди, оставив вас наедине и с гостями и цыганами и прочим сбродом. Будет вам тогда и тихо, но нервно. Пока у нас как в том старом анекдоте. Помог, чем смог, картошку сажайте сами :) Так что давайте не будем тошнить на нервы друг другу.

Мама пишет в тюрьму сыну: 

"Сынок, как тебя посадили, сил нет, некому помогать по хозяйству - огород не вскопанный, картошка не посажена, что делать не знаю!" Сын пишет ответ: 

"Мама в огороде не копайся, накопаешь такого, что и тебя посадят и мне срок добавят". Мама опять пишет сыну: 

"Сынок, как пришло твое письмо, приехали мусора, перекопали весь огород, ничего не нашли - уехали злые, матерились".

Сын пишет ответ: 

"Мама! Чем мог - тем помог, картошку сажайте сами". 

Life23
Offline
Зарегистрирован: 10.08.2013

да никому я не собирался выносить мозг!!! Вас никто не заставлял отвечать в ветке! если для Вас это тупые вопросы, зачем было отвечать на них? И вообще, мы здравые люди и я думаю эти споры и разборки ни к чему..

leshak
Offline
Зарегистрирован: 29.09.2011

Life23 пишет:

ну как то вот так у меня получилось(только вместо отправки мигаю два раза светиками для проверки на железе):

Вообщем, кто бы там чего не зубоскалил, вы конечно молодец, но....

"....оплеухи нужней поцелуев,
поцелуям мы знаем цену..." (с) Дольский

Итак, давайте поищем что можно раскритиковать в вашем скетче :)  (и чем его улучшить). 

Во первых, в оригинальном скетче переменные работы с кнопками были банально более удачно названы. Тот скетч я смотрел и без всяких подсказок и комментариев мне было понятно, что условие

if (prevBtn != currBtn && currBtn == HIGH)

 Означает "изменилось состояние кнопки, при этом текущие состояние кнопки - нажато"

У вас же "digitalRead(2)==HIGH&&flag==0" , что на человеческий язык переводится - гораздо трудней. flag - не прочитав весь остальной код - не поймешь его смысл. К тому же ... он меняется у вас там где светики мигают, а в оригинале было четко разделено "вот код работы с кнопками и принятие решений" (весь в одном месте), а вот отдельно отсылка SMS-ски :)

Не знаю ваш уровень english, но возможно вы просто не поняли откуда взялись эти названия переменных, поэтому они вам "ничего не сказали" (а нужно старатся что-бы код "сам рассказывал что делает").

prev - сокращение от "previous - предыдущий".
Btn - сокращение от "Button - кнопка"
curr - сокращение от "current - текущие, нынешнее (состояние)" 

Следовательно когда я вижу prevBtn и currBtn я сразу читаю "прошлое состояние кнопки", и "текущие состояние кнопки" :)   

А когда я вижу flag - я понимаю только что это какая-то переменная принимающая true/false. Семантика ее - прошла мимо меня.

Так что попробуйте, все-таки условия "кнопку нажали" и "кнопку отпустили" переписать в стиле вашего изначального скетча. Он вообщем-то был "хорошим примером". C говорящими именами переменных и без "размазывание" кнопочной логика в разные места :)

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Life23 пишет:

да никому я не собирался выносить мозг!!! Вас никто не заставлял отвечать в ветке! если для Вас это тупые вопросы, зачем было отвечать на них? И вообще, мы здравые люди и я думаю эти споры и разборки ни к чему..

И тем неменее, ВЫ на провокацию повелись и решили нам доказать что не лапти щи хлебаете и полезли лопатить код своими ручками:)

Так что миссия удалась, welcome aboard. гы гы

А про шоколадку вы здря, собак не кормят шоколадом, для собак шоколад это смерть.. Эт я просто вспомнил как Шелдон тренировал Пени в Теории большого взрыва.. :)

leshak
Offline
Зарегистрирован: 29.09.2011

Далее, смотрите, у вас в скетче затесался "аттавизм" от оригинально.

int btnPin = 2;

При этом, в коде оно нигде не используется.

А сама идея - хорошая. analogRead(2) - фиг его пойми что значит, а когда читаешь analogRead(btnPin) - сразу понимаеш что это чтение состояние кнопки :)

Второй плюс, когда номера пинов вынесены в одно место и имеют имена... если вам потребовалось перенсти кнопку на другой пин, то в случае если у вас было

digitalWrite(7,...)

в 30-ти местах, и вы вдруг решили перевесить светик на 13-тый пин, то вам нужн обудет менять в 30-ти местах код. Внимательно. Нигде не пропустить. Если же вы изначально сделали

int redLedPin = 7;
....
digitalWrite(redLedPin,HIGH)

То поменять номер пина нам нужно будет только в одном месте. Да и читать такое легче. Сразу понятно "включили красный светодиод" :)

Только я бы, наверное даже не "переменную делал" под номер пина, а ключевым словом #define воспользовался

#define RED_LED_PIN 7
#define GREEN_LED_PIN 8

setup(){
  pinMode(RED_LED_PIN,OUTPUT);
  pinMode(GREEN_LED_PIN,OUTPUT);

}

loop(){

  ....
   digitalWrite(RED_LED_PIN,HIGH); // включили красный светодиод
   digitalWrite(GREEN_LED_PIN,LOW);  // выключили зеленый
  ...
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

Ползем далее. Смотрим на функции Comand_high() и Command_low()

Если вы смогли выкинуть из них вашу переменную flag, то они стали отличатся только одной вещью - номером пина которым они мигают :)

Следовально, вместо двух функций, мы можем использовать одну. А номер пина - передавать в нее параметром.  ну и назовем ее попонятней.

blinkLed - мигать светодиодом.

void blinkLed(byte ledPin)
{

    digitalWrite(ledPin, HIGH);
    delay(300);

    digitalWrite(ledPin,LOW);
    delay(300);

    digitalWrite(ledPin, HIGH);
    delay(300);

    digitalWrite(ledPin, LOW);


 }

А использовать ее будем так:

blinkLed(RED_LED_PIN); // помигали красным светиком

....

blinkLed(GREEN_LED_PIN); // помигали зеленым светиком

 

leshak
Offline
Зарегистрирован: 29.09.2011

Смотрим на наш blinkLed и понимаем что он не идеален :)

А если нам нужно будем мигнуть 100-ть раз? Что так и будем 100 раз копировать digitalWrite/delay?  

Тут нам поможет for

void blinkLed(byte ledPin)
{
  for(byte i=0;i<2;i++){ // мигнуть два раза
      digitalWrite(ledPin, HIGH);
      delay(300);

     digitalWrite(ledPin,LOW);
      delay(300);
   }

 }

P.S. Кстати - забыл вас пнуть за то отвратительное название темы. "Помогите новичку". В качестве домашнего задания - сами найдите поиском мою обычную ругань по этому поводу :)

Life23
Offline
Зарегистрирован: 10.08.2013

уфф.....  Puhlyaviy, где Вы там со своей водой в бутылке с разбрызгивателем?...

пытаюсь "переварить" написанное leshak...

Life23
Offline
Зарегистрирован: 10.08.2013

тяжеловото.. 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Life23 пишет:

тяжеловото.. 

процес формирования новых связей в мозгу всегда тяжело проходит.. потом легче пойдет... главно начать.. ( допивает воду из бутылки)

leshak
Offline
Зарегистрирован: 29.09.2011

Life23 пишет:

тяжеловото.. 

Первый раз и на бабу влезть не просто... зато потом :)

Не пытайтесь переварить "сразу все". Не хватайтесь перепахивать сразу весь скетч.

Каждый шаг что я описывал - подразумевает что мы в его начале и конце имеем рабочий скетч. Более того - "внешнее поведение" даже не меняется. Так что пытайтесь применять эти советы "по очереди", а не все сразу. Для начала - вернитесь, к prevBtn/currBtn. Там всего пару строчек вам поменять прийдется (а свои функции мигания диодом - оставте "как есть").

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Универсалить - так универсалить! Домашнее задание разобраться нафига я это изменил и почему такие типы.

void blinkLed(byte ledPin, int blinkCount, long blinkDelay)
{
  for(byte i=0;i<blinkCount;i++){ // намигаться по самое нехочу
      digitalWrite(ledPin, HIGH);
      delay(blinkDelay);

     digitalWrite(ledPin,LOW);
      delay(blinkDelay);
   }

 }

ПС: "100-ть" - блин! Как это прочитать? Ничего умнее "Хундырть" в глову не идет :)

Life23
Offline
Зарегистрирован: 10.08.2013

leshak, да вот по очереди и пытаюсь все соображать.. 

=========

Далее, смотрите, у вас в скетче затесался "аттавизм" от оригинально.

1 int btnPin = 2;

===========

тут вкурил.. что надо было вот так:

 

  if (digitalRead(btnPin)==HIGH&&flag==0)

 

JollyBiber сам  затормозил на этом месте )))

leshak
Offline
Зарегистрирован: 29.09.2011

И да... у вас сейчас могут быть проблемы с детектом "нажали/отпустили" кнопку.  Пока светоиод мигает - ардуина забивает болт на изменение состояния кнопок.

Пока и вы, забейте болт на эту проблему. Нажимйте отпускайте кнопку с интервалом 2-3-секунды. Когда светики уже отмигали.

Пусть, вначале, хоть так заработает. 

А уж потом - вернем к этой проблеме, устраним "тупняки" :)

leshak
Offline
Зарегистрирован: 29.09.2011

Life23 пишет:

leshak, да вот по очереди и пытаюсь все соображать.. 

Не нужно "соображать", нужно делать. По одному шагу. Следующий шаг опирается на предыдущий. Когда вы сделаете в коде, вам проще будет понять что делать в следующем. Навык "представить как будет выглядит скетч после 5-ти изменений" - он позже прийдет :)

>тут вкурил.. что надо было вот так

Угу. Только вначале нужно было избавится от неудачного flag :) и убрать digitalRead из условия. Предыдущий шаг пропустили :( Вернитесь к истокам - смотрите как это было сделано в стартовом скетче. Первое условие - вам даже менять не нужно было. А второй if - написать полностью "по аналогии".

leshak
Offline
Зарегистрирован: 29.09.2011

JollyBiber пишет:

Универсалить - так универсалить! 

Не... тут пока универсалить особо не нужно. Мы же все равно будем ее переделывать на "без delay()"

Да и это все-таки "временно вспомогательная функция". Потом же у нас будет заменятся на sendSMS

IMHO то что уже есть "достаточно универсально": передачу параметра - показали, использование for - попробовали, вынос конфигурации пинов в дефайны - тоже есть. Не стоит мучать далее :)

JollyBiber пишет:

Домашнее задание разобраться нафига я это изменил и почему такие типы.

Тогда я и вам домашнее задание задам: перечитать документацию на функцию delay и подумать так ли уж идеально вы выбрали типы :) По крайней мере один из них.

Update: даже два. Слабо мигнуть минус 3 раза? :)

 

 

Life23
Offline
Зарегистрирован: 10.08.2013

получилось... но надо идти за пивом, а то извилины уже дымлят...

int btnPin = 2;
boolean prevBtn = LOW;
void setup()   
 { 
    pinMode(7, OUTPUT); 
    pinMode(8, OUTPUT);
    pinMode(2, INPUT); 
  }  
 void loop()
  { 
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
         Comand_high();
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       Comand_low();
     }
     prevBtn = currBtn;
}

функции Comand_hight и Comand_low не писал в коде, так как пока остались прежними.. 

Life23
Offline
Зарегистрирован: 10.08.2013

Навел порядок немного:

#define HIGH_LED_PIN 7
#define LOW_LED_PIN 8
int btnPin = 2;
boolean prevBtn = LOW;
void setup()   
 { 
    pinMode(HIGH_LED_PIN, OUTPUT); 
    pinMode(LOW_LED_PIN, OUTPUT);
    pinMode(btnPin, INPUT); 
  }  
 void loop()
  { 
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
         Comand_high();
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       Comand_low();
     }
     prevBtn = currBtn;
}
void Comand_high()
{
    digitalWrite(HIGH_LED_PIN, HIGH);
    delay(300);
    digitalWrite(HIGH_LED_PIN,LOW);
    delay(300);
    digitalWrite(HIGH_LED_PIN, HIGH);
    delay(300);
    digitalWrite(HIGH_LED_PIN, LOW);
    }
void Comand_low()
{
    digitalWrite(LOW_LED_PIN, HIGH);
    delay(300);
    digitalWrite(LOW_LED_PIN,LOW);
    delay(300);
    digitalWrite(LOW_LED_PIN, HIGH);
    delay(300);
    digitalWrite(LOW_LED_PIN, LOW);
}

а вот по поводу:

void blinkLed(byte ledPin) - мне не понятно пока.. 

 

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Дык я же не говорил что "мой вариант беспрекословно идеальный" - это и так всем понятно ;)

 

leshak
Offline
Зарегистрирован: 29.09.2011

Пока - зашибок.

Life23 пишет:

а вот по поводу:

void blinkLed(byte ledPin) - мне не понятно пока.. 

Смотрите. У вас есть две функции. Comand_high() и Comand_low(). Которые отличаются только одной вещью - каким пином они мигают. Во всем остальном - это дублирование кода. Которого желательно избегать (хотя-бы из лени).

То есть нам нужно написать новую функцию. Аналогичную Command_high() (почти идентичную), но каким именно пином мигать, будет зашито не в саму функцию, а мы будем сообщать ей когда делаем вызов самой функции. То есть - нам нужно научится передавать параметр в функцию.

Поэтому мы читаем Функции | Аппаратная платформа Arduino

и думаем как же написать такую функцию (или ищем ее выше по ветке :)

Кстати, передавать параметр в функцию мы уже умеем :)  когда вы делаете digitalWrite(7,HIGH); вы же сообщаете функции какой пин и в какое значение нужно установить?  Если бы не возможность передавать параметры, то представте сколько почти одинаковых функций пришлось бы написать авторам ардуины: digitalWrite_7_HIGH(), digitalWirte_7_LOW(), digital_8_HIGH() и т.д. и т.п. Слава богу они были ленивы и написали всего одну функцию. Которую можно использовать с разными пинами.

Теперь вам - нужно написать функцию, которая умеет принимать один параметр и использует его в качестве номера пина для мигания.

P.S. Кстати в C/C++ принято называть функции с маленькой буквы. Как-бы "джентельменское соглашение". Что-бы все было однотипно и не гадать.

 

Life23
Offline
Зарегистрирован: 10.08.2013

правильно?

#define HIGH_LED_PIN  7
#define LOW_LED_PIN  8
int btnPin = 2;
boolean prevBtn = LOW;
void setup()   
 { 
    pinMode(HIGH_LED_PIN, OUTPUT); 
    pinMode(LOW_LED_PIN, OUTPUT);
    pinMode(btnPin, INPUT); 
  }  
 void loop()
  { 
    int i=HIGH_LED_PIN;
    int j=LOW_LED_PIN;
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
         blinkLed(i);
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       blinkLed(j);
     }
     prevBtn = currBtn;
}
void blinkLed(byte ledPin)
{
    digitalWrite(ledPin, HIGH);
    delay(300);
    digitalWrite(ledPin,LOW);
    delay(300);
    digitalWrite(ledPin, HIGH);
    delay(300);
    digitalWrite(ledPin, LOW);
 }

теперь попробую разобраться с функцией void blinkLed..

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Могут ли у Вас меняться значения HIGH_LED_PIN и LOW_LED_PIN ?

Life23
Offline
Зарегистрирован: 10.08.2013

JollyBiber не совсем понял вопроса... или пока не понял..

кстати, применил Ваш код для функции blinkled:

получилось вот так:

#define HIGH_LED_PIN  7
#define LOW_LED_PIN  8
int btnPin = 2;
boolean prevBtn = LOW;
void setup()   
 { 
    pinMode(HIGH_LED_PIN, OUTPUT); 
    pinMode(LOW_LED_PIN, OUTPUT);
    pinMode(btnPin, INPUT); 
  }  
 void loop()
  { 
    int i=HIGH_LED_PIN;
    int j=LOW_LED_PIN;
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
         blinkLed(i,5,300);
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       blinkLed(j,5,300);
     }
     prevBtn = currBtn;
}
void blinkLed(byte ledPin, int blinkCount, long blinkDelay)
{
  for(byte x=0;x<blinkCount;x++){ 
      digitalWrite(ledPin, HIGH);
      delay(blinkDelay);
      digitalWrite(ledPin,LOW);
      delay(blinkDelay);
   }
 }

JollyBiber помоему я понял что вы хотели сказать этим вопросом..  

    int i=HIGH_LED_PIN;
    int j=LOW_LED_PIN;

 

это лишнее?

правильно будет вот так?

#define HIGH_LED_PIN  7
#define LOW_LED_PIN  8
int btnPin = 2;
boolean prevBtn = LOW;
void setup()   
 { 
    pinMode(HIGH_LED_PIN, OUTPUT); 
    pinMode(LOW_LED_PIN, OUTPUT);
    pinMode(btnPin, INPUT); 
  }  
 void loop()
  { 
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
         blinkLed(HIGH_LED_PIN,5,300);
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       blinkLed(LOW_LED_PIN,5,300);
     }
     prevBtn = currBtn;
}
void blinkLed(byte ledPin, int blinkCount, long blinkDelay)
{
  for(byte i=0;i<blinkCount;i++){ 
      digitalWrite(ledPin, HIGH);
      delay(blinkDelay);
      digitalWrite(ledPin,LOW);
      delay(blinkDelay);
   }
 }

 

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Правильно :) Теперь рассмотрим вариант про который писал leshak:

что сейчас произойдет?

blinkLed(LOW_LED_PIN, -5, -300);

И как это победить? Подсказка

leshak
Offline
Зарегистрирован: 29.09.2011

>это лишнее?

Ну как-бы да. Вводить отдельную локальную переменную, вам нужно было-бы вы собирались, сделато что-то, скажем "помигать всеми диодами по очереди". Что-бы если у вас, скажем 10-ть диодов, не писать 10-ть раз blinkedLen, а сделать что-то типа

for(byte i=2;i<=12;i++)blinkLed(i); // мигаем, по очереди, диодами с 2 до 12-тый

 

leshak
Offline
Зарегистрирован: 29.09.2011

JollyBiber пишет:

Правильно :) Теперь рассмотрим вариант про который писал leshak:

что сейчас произойдет?

blinkLed(LOW_LED_PIN, -5, -300);

И как это победить? Подсказка

Эм.. "разобратся с типами" - это хорошо. Но все-таки невозможно охватить сразу все :) Тем более что это было ваше домашние задание :)

2Life23:

Поэтому, я пока предлагаю не усложнять. Пусть у нас blinkLed принимает один параметр. Настраивать сколько раз мигать, как быстро... для текущей задачи не критично. Есть более актуальные  проблемы. 

Например избавление от delay() (а потом у нас "дребезг" может вылезти) :)

Вначале добъемся что-бы "работало как нужно", а уж потом будем добавлять "пасхальные яйца" :)

Вы наблюдаете, предсказанную мной проблему?  Пока диод не закончил мигание - скетч ни на что не реагирует?

Если наблюдаете, то для начала попробуйте понять

а. Почему это происходит (и глядя в код попытатся предсказать точное время "тупления" :)
б. Как работает пример Мигаем светодиодом без delay() | Аппаратная платформа Arduino

Вначале хотя-бы прочитайте и разберите построчно.  Вряд ли у вас получится, сразу, адаптировать его под себя (подсказка: для этого прийдется разбить blinkLed на две функции. Одна будет "устанавливать чем мигать нужно", а вторая "выполнять мигание когда пришло время"), так что "вникнуть" пока достаточно :)

leshak
Offline
Зарегистрирован: 29.09.2011

Хм... кстати... по поводу ухода от реальной задачи.

Мы так бодро занялись диодами и миганиями, что забыли об изначальной задаче - отправке SMS.

Может вернемся к ней? Life23 как вы на это смотрите? Как я понимаю, вы перешли на мигание диодом, что-бы не тратить деньги на SMS, в период отладки. Но есть - более прямое решение этой задачи, показать?

Life23
Offline
Зарегистрирован: 10.08.2013

а. Почему это происходит (и глядя в код попытатся предсказать точное время "тупления" :)

время "тупления" = delay(blinkDelay)+delay(blinkDelay)

то что описанно в void blinkLed 

+такты перехода.

а сам "delay" останавливает все рабуту контроллера, пока не отсчитает параметр в самом dalay.

естественно по первому фронту сигнала с кнопки срабатывает одно из условий:

if (prevBtn != currBtn && currBtn == HIGH) {
         blinkLed(HIGH_LED_PIN,5,300);
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       blinkLed(LOW_LED_PIN,5,300);

остальной "дребезг" уходит в игнор, пока выполняеться delay. 

Life23
Offline
Зарегистрирован: 10.08.2013

"Как я понимаю, вы перешли на мигание диодом, что-бы не тратить деньги на SMS, в период отладки."

это действительно так. плюс затрата на время проверки.

"Но есть - более прямое решение этой задачи, показать?"

был бы очень благодарен! ;)

Но все эти "уроки" очень полезны - за что очень Вам благодарен!

update: вместо св.диодов использавать терминал?

leshak
Offline
Зарегистрирован: 29.09.2011

Life23 пишет:

update: вместо св.диодов использавать терминал?

Точняк :)

Главная задача - заранее писать так, что бы потом, когда все отладится на Serial, перейти на использование реального шилда, с минимальными усилиями.

Для этого, мы можем применить ту же самую технику, которую использовали для "а вдруг у нас номера пинов поменяются".

Пишем вверху (чуть ниже gprsSerial(3,2))

#define GPRS Serial

Мы создали "псевдоним" GPRS. При компиляции он, автоматически будет заменятся на Serial

затем берем ваш изначальный скетч и везде, кроме строки SoftwareSerial gprsSerial(3, 2); заменяем gprsSerial на GPRS

У нас полчится что-то типа

GPRS.begin(9600)
....
GPRS.print(....

и т.д.

После чего открываем Serial. и смотрим "что же там наш скет посылает шилду" :)

Когда все отладим, переключится "на настоящий шилд" мы сможем заменой одной строчки.

Поменяем 

#define GPRS Serial

на

#define GPRS gprsSerial

Кстати, подобный подход не толко деньги вам съекономит, но и.... позволит другим людям, тем у кого нет шилда - запустить/пощупать ваш код. Что, опять-таки - повысит шансы на помощь форума.

Так что - всегда старайтесь свои проблемы/примеры по возможности сводить к использованию Serial - он есть у всех :)

Life23
Offline
Зарегистрирован: 10.08.2013

сильно не ругайте..


#define GPRS Serial
int btnPin = 2;
int i;
boolean prevBtn = LOW;
char* myStrings[]={"Knopka ON", "Knopka OFF"};

void setup()
{
    GPRS.begin(9600);
    delay(100);
}
void loop()
  { 
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
       i=0;
         sendTextMessage(); 
     }
     if (prevBtn != currBtn && currBtn == LOW) {
        i=1;
       sendTextMessage();    
     }
     prevBtn = currBtn;
}
void sendTextMessage() {
    GPRS.println(myStrings[i]);
    delay(1000);
 
}

использовал все что знаю на данный момент..

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

можно сэкономить переменную "i" Выкиньте ее и подправьте функцию sendTextMessage ;)

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

А следующий ход - вернуть ее назад и убрать sendTextMessage из "if"-ов ;)

leshak
Offline
Зарегистрирован: 29.09.2011

Не, ну че.. нормалек.

Только...

шо же вы так укоцали sendTextMessage()? Выкинули из нее все что только можно?

Если вы сейчас подмените Serial на настоящий gprsSerial - оно же не заработает.

Пусть будут все эти "AT+CMGF=1\r". Если вы их увидите в Serial Monitor вы же не убежите с криком "мама, чтоо это.."? ;)
Наоборот, получите уверенность что "вот... нужные служебные команды тоже отсылаются". Среди них - и свои "Knopka ON" и "Knopka Off" увидите.

Вам же нужно все отладить так, что-бы потом только "поменяв одну строчку" запустить все на реальном железе. Поэтому чем ближе к реальности будет скетч, чем меньше прейдется "дописывать/менять" при переходе к реальности - тем лучше (и потом еще не раз, возможно прийдется обратно "от реального" к "отладочному" варианту возвращатся. если какие-то "косяки" вылезут).

То что индекс строки вы передаете в фунцию с помощью глобальной переменно i это...

Молодец, конечно, выкрутился :) Работать будет. Только шо же мы так параметров функции боимся? Они не кусаются. Вроде же, уже, когда писали  blinkLed то передавали пин которым нужно мигать в качестве параметра. Почему тут так же не сделать?

Сделайте что-бы вместо двух строк

 i=1;
sendTextMessage()

Можно было написать одну

 sendTextMessage(1);

И переменную i - вообще выкинуть.

Кстати - неудачно вы ей имя дали. Традиционно переменные i,j используется в качестве итераторов (счетчиков) когда мы проходим по массиву с помощью for. Поэтому любой читающий код, и видящий что-то myStrings[i] интуитивно ищет глазами цикл :)

Имя, скажем messageIndex или messageIdx или msgIdx - было-бы гораздо более подходящим :) 

Life23
Offline
Зарегистрирован: 10.08.2013

покоцал - что бы легче понимать принцип работы программы. Да и на форум не засорять.. Конечно я понимаю, что реальный шилд не будет работать с таким  кодом. Перед тем как вставить код на форуме, я 100 раз проверил работу полного кода.

 

по поводу переменной i сам уже понял, что она в основном используеться в счетчиках.. :)

а с параметрами функции деуствительно пока "страхи" :)).

но вижу не миновать мне их никак... пока разобрался с char и как правильно вписать ее в serial.print - запутался совсем..

перекур - и иду дальше в сторону "параметров функции")) 

leshak
Offline
Зарегистрирован: 29.09.2011

JollyBiber пишет:

А следующий ход - вернуть ее назад и убрать sendTextMessage из "if"-ов ;)

А вот это - не нужно.

Life23
Offline
Зарегистрирован: 10.08.2013

мдаа.. действительно не стоит бояться пераметров функции.. ))

#define GPRS Serial
int btnPin = 2;
boolean prevBtn = LOW;
char* myStrings[]={"Knopka ON", "Knopka OFF"};
void setup()
{
    GPRS.begin(9600);
    delay(100);
}
void loop()
  { 
    boolean currBtn = digitalRead(btnPin);
    if (prevBtn != currBtn && currBtn == HIGH) {
         sendTextMessage(0); 
     }
     if (prevBtn != currBtn && currBtn == LOW) {
       sendTextMessage(1);    
     }
     prevBtn = currBtn;
}
void sendTextMessage(int sms) {
    GPRS.println(myStrings[sms]);
    delay(1000);
}