Вызов подпрограммы из библиотеки

SFU
Offline
Зарегистрирован: 08.01.2017

  Как из созданной самим библитеки можно вызвать подпрограмму, которая будет реализована в основной программе? Т.е из файла моя_библиотека.ccp  сделать обращение к подпрограмме которая будет в файле моя_программа.ino ?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

SFU, ну что за тайны. У меня есть это, и как из этого , получить это с помощью этого.

Ладно. Каков вопрос - таков и ответ.

slava.ru38_v2_lib.ino

/*slava.ru38_v2_lib.ino
#1 светодиод  (Led) пока мигает программа работает, перестала зависла программа
#2 УЗ датчики
датчик УЗ левый   trig ->14 (L_TRIG_pin)
                  echo ->15 (L_ECHO_pin)
датчик УЗ средний trig ->10 (Utrasonic_C_trig_pin)
                  echo ->11 (C_ECHO_pin)
датчик УЗ правый  trig ->12 (R_TRIG_pin)
                  echo ->13 (R_ECHO_pin)
#3 датчики линии
датчик линии левый    ->19 (L_LinSen_pin)   0 нормально / 1 фиксирует линию
датчик линии правый    ->18 (R_LinSen_pin) 0 нормально / 1 фиксирует линию
#4 моторы
Мотор правый  ENA ->5 (M1_ENA_pin) скорость
              IN1 ->4 (M1_IN1_pin) вперед
              IN2 ->3 (M1_IN2_pin) назад
Мотор левый   ENA ->9 (M2_ENA_pin) скорость
              IN1 ->8 (M2_IN1_pin) вперед
              IN2 ->7 (M2_IN2_pin) назад

*/
//#1 мигающий светодиод
const int Led_pin = 2; // задание номера вывода световой сигнализации
bool Led = 0; // этой переменной устанавливаем состояние светодиода
//#4 моторы
#include "Cl_Motor.h"
Cl_Motor M1(5, 4, 3, 255); // создать мотор 1 (ENA=5,N1=4,N2=3,SPEED=255) 255 максимальная скорость
Cl_Motor M2(9, 8, 7, 255); // создать мотор 2 (ENA=9,N1=8,N2=7,SPEED=255) 255 максимальная скорость
//#3 УЗ датчики
const int L_TRIG_pin = 14; // задание номера вывода левого trig УЗ датчика
const int L_ECHO_pin = 15; // задание номера вывода левого echo УЗ датчика
const int C_TRIG_pin = 10; // задание номера вывода центрального trig УЗ датчика
const int C_ECHO_pin = 11; // задание номера вывода центрального echo УЗ дачика
const int R_TRIG_pin = 12; // задание номера вывода правого trig УЗ датчика
const int R_ECHO_pin = 13; // задание номера вывода правого echo УЗ датчика
long distL = 0; // дистанция, измеренная левым УЗ датчиком
long distC = 0; // дистанция, измеренная центральным УЗ датчиком
long distR = 0; // дистанция, измеренная правым Уз датчиком
// **************************Измерение дистанции*********************
long Utrasonic(int TRIG_pin, int ECHO_pin) {  // измерение дистанции левым УЗ датчиком
  digitalWrite(TRIG_pin, 1);
  delay(10);
  digitalWrite(TRIG_pin, 0); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
  return pulseIn(ECHO_pin, 1) / 58;
}
// #4 датчики линии
const int L_LinSen_pin = 19; // вход левого датчика линии
const int R_LinSen_pin = 18; // вход правого датчика линии
bool L_LinSen; // статус левого сенсора
bool R_LinSen; // статус правого сенсора

void setup () {
  Serial.begin(9600); // запускаем серийный порт (скорость 9600)
  //#1 мигающий светодиод
  pinMode(Led_pin, OUTPUT); //Подключим светодиод
  digitalWrite(Led_pin, Led = 0);
  //#2 УЗ датчики
  pinMode( L_TRIG_pin, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
  pinMode( L_ECHO_pin, INPUT); // задание режима работы вывода левого echo УЗ датчика
  pinMode( C_TRIG_pin, OUTPUT); // задание режима работы вывода центрального trig УЗ датчика
  pinMode( C_ECHO_pin, INPUT); // задание режима работы вывода центрального echo УЗ датчика
  pinMode( R_TRIG_pin, OUTPUT); // задание режима работы вывода правого trig УЗ датчика
  pinMode( R_ECHO_pin, INPUT); // задание ражима работы вывода правого echo УЗ датчика
  // #3 датчики линии
  pinMode (L_LinSen_pin, INPUT); // определением pin левого датчика линии
  pinMode (R_LinSen_pin, INPUT); // определением pin правого датчика линии
  //#4 моторы
  M1.in_setup();// инициализировать мотор 1
  M2.in_setup();// инициализировать мотор 2
}

void loop () {
  static uint32_t past_1 = 0;
  if (millis() - past_1 >= 500) {// если подошло 0,5 секунды
    past_1 = millis();
    //#1
    digitalWrite(Led_pin, Led = ! Led); // переключим светодиод
    //#2 УЗ датчики
    distL = Utrasonic( L_TRIG_pin , L_ECHO_pin);
    Serial.println(distL);
    distC = Utrasonic( C_TRIG_pin , C_ECHO_pin);
    Serial.println(distC);
    distR = Utrasonic( R_TRIG_pin , R_ECHO_pin);
    Serial.println(distR);
    //#3 датчики линии
    L_LinSen = digitalRead (L_LinSen_pin); // считываем сигнал с левого датчика полосы
    R_LinSen = digitalRead (R_LinSen_pin); // считываем сигнал с правого датичка полосы
    //#4 моторы
    if (distL > 50 && distC > 50 && distR > 50 && ! L_LinSen )   M1.FORWARD();
    else  M1.STOP();
    if (distL > 50 && distC > 50 && distR > 50 && ! R_LinSen )   M2.FORWARD();
    else  M2.STOP();
  }
}
// Cl_Motor.cpp

#include "Arduino.h"
#include "Cl_Motor.h"

Cl_Motor::Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed) { // конструктор
  ENA_pin = _1pin; // пин  ENA
  N1_pin = _2pin; // пин  N1
  N2_pin = _3pin; // пин  N2
  Speed = _speed; // скорость мотора
}
void Cl_Motor::in_setup() { // функцию засунуть в setup() программы
  Motor = 0;
  analogWrite (ENA_pin, Speed);
  pinMode (N1_pin, OUTPUT);
  digitalWrite(N1_pin, 0);
  pinMode (N2_pin, OUTPUT);
  digitalWrite(N2_pin, 0);
}
void Cl_Motor::FORWARD() { // запустить мотор вперед
  if (Motor != 1) {
    Motor = 1;
    digitalWrite(N1_pin, 1);
    digitalWrite(N2_pin, 0);
  }
}
void Cl_Motor::BACKWARD() { // запустить мотор назад
  if (Motor != 2) {
    Motor = 2;
    digitalWrite(N1_pin, 1);
    digitalWrite(N2_pin, 0);
  }
}
void Cl_Motor::STOP() { // остановить мотор
  if (Motor != 0) {
    Motor = 0;
    digitalWrite(N1_pin, 0);
    digitalWrite(N2_pin, 0);
  }
}

Cl_Motor.h

// Cl_Motor.h
#ifndef Cl_Motor_h
#define Cl_Motor_h

#include "Arduino.h"

class Cl_Motor {
  public:
    Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed); // конструктор
    void in_setup(); // функцию засунуть в setup() программы
    void FORWARD(); // запустить мотор вперед
    void BACKWARD(); // запустить мотор вперед
    void STOP();// остановить мотор
  private:
    byte ENA_pin; // пин  ENA
    byte N1_pin; // пин  N1
    byte N2_pin; // пин  N2
    byte Speed; // скорость мотора
    byte Motor;// 1 мотор вращается вперед/2 мотор вращается назад / 0 нет

};
#endif // Cl_Motor.h

 

SFU
Offline
Зарегистрирован: 08.01.2017

qwone, а если бы в Вашем примере в slava.ru38_v2_lib.ino, скажем была бы подпрограмма void primer1(),  и Вам нужно было бы к ней обратится из void FORWARD()?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну да. Если бы не было класса, я обратился на прямую, а не как функцию представителя класса.

SFU
Offline
Зарегистрирован: 08.01.2017

НЕТ! Вы опять не поняли вопроса... Предположим, что методу FORWARD() из вашей библиотеки требуется обращение к какой либо подпрограмме из slava.ru38_v2_lib.ino ( в Вашем примере , правда нет подпраграмм). Т. е . методе FORWARD() вашей библиотеки должен быть вызов подпрограммы из основной программы проекта.


qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Похоже вам надо перечитать  Б. Страуструпа «Язык программирования С++»

SFU
Offline
Зарегистрирован: 08.01.2017

Благодарю за совет! Книгу скачал. Буду читать...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В библиотеке объявите указатель на функцию. В начале скетча (в setup, например) присвойте этому указателю адрес нужной функции. А потом из библиотеки вызывайте эту функцию сколько влезет.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

example.ino

/* example.ino
*/
#include "file.c"
byte aaa = 1;
byte bbb = 3;
void setup() {
  Serial.begin(9600);
  Serial.println(func(aaa, bbb));//<-- функция с file.c
}

void loop() {
}

file.c

/* file.c
*/
// файлы обеспечивающие работу этого файла
#include <math.h>           // поддержка математики 
#include <stdlib.h>         // ???
#include <inttypes.h>       // поддержка типов
#include <avr/io.h>         //???
#include <avr/interrupt.h>  // ???
#include "Arduino.h"        // для  digitalWrite


// функция перенесеная с .ino
byte func(byte a, byte b) {
  return a + b;
}

 

negavoid
Offline
Зарегистрирован: 09.07.2016

qwone пишет:

example.ino

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

project.ino

#include "reg_callback.h"
#include "reg_callback.c"

int my_callback(int x)
{
  Serial.println(x * 2, DEC);
}

void setup() {
  Serial.begin(9600);

  callback ptr_my_callback = my_callback;
  register_callback(ptr_my_callback);
}

void loop() {
  do_something(42);
  delay(1000);
}

reg_callback.h

typedef int (*callback)(int);
void register_callback(callback ptr_reg_callback);

int do_something(int);

reg_callback.c

#include "reg_callback.h"

callback func;

void register_callback(callback ptr_reg_callback)
{
  func = ptr_reg_callback;
}

int do_something(int x)
{
  return func(x);
}

 

SFU
Offline
Зарегистрирован: 08.01.2017
void (*regim0) ()=&nullmetod;
void(*regim1) ()=&nullmetod;

Вот так я объявляю указатель на функции  и присваиваю им ссылку на пустой метод nullmetod из  той же библиотеки

encoder1.regim0=r0;
encoder1.regim1=r1;

а вот так в setup присваиваю указателю ссылку на подпрограммы r0() и r1().

В итоге компилятор на строки из библиотеки ругается: cannot convert.......

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Блин , вы хоть умеете объявлять функции.

void func1(void); // вот объявление функций
void func2(byte aa); // вот объявление функций
void func3(byte); // вот объявление функций
void (*regim0) (void)=&nullmetod;
void (*regim1) (int)=&nullmetod;

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

В библиотеке объявите указатель на функцию. В начале скетча (в setup, например) присвойте этому указателю адрес нужной функции. А потом из библиотеки вызывайте эту функцию сколько влезет.

Так вот кто у нас любитель реентерабельных кодов )))

pavel747123
Offline
Зарегистрирован: 10.01.2017

Ребята подскажите как правильно паписать свою библиотеку на ардуино
Я еще новичок

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

pavel747123 пишет:
Ребята подскажите как правильно паписать свою библиотеку на ардуино Я еще новичок

Вот так сел за компьютер и пишешь. 

/* bounce_hcpp.ino
  #2 cветодиод -> 13 (Led_pin)
  #1 кнопка    -> 2  (Btm_pin)0 нажата /1 нет
*/
// #1 cветодиод
const int Led_pin = 13; // нога на светодиоде
bool Led; // состояние светодиода
void Led_invert(void) { // поменять состояние светодиода
  digitalWrite(Led_pin, Led = ! Led);
}
// #2 кнопка
#include "cl_bounce.h"
#define Btm_pin 2 // подключим кнопку на выв 2
cl_bounce Btm(Btm_pin);
void setup() {
  // #1 cветодиод
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(Led_pin, Led = ! Led);
  //#2 кнопка
  Btm.setup();
}

void loop() {
  //#1
  //#2 кнопка
  Btm.loop(& Led_invert);

}

cl_bounce.h

// cl_bounce.h

#ifndef cl_bounce_h
#define cl_bounce_h

#include "Arduino.h"

class cl_bounce {
  public:
    cl_bounce(byte pin);
    void setup(void);
    void loop(void *func(void));
  private:
    byte btn_pin ; // вывод кнопки
    bool btn, btn_old; // значение на кнопке без дребезга, тоже но стар значение
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
};

#endif // cl_bounce_h

cl_bounce.cpp

//cl_bounce.cpp

#include "Arduino.h"
#include "cl_bounce.h"

cl_bounce::cl_bounce(byte pin)  {
  pinMode(pin, OUTPUT);
  btn_pin = pin;
}

void cl_bounce::setup(void) {
  pinMode(btn_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой
  btn = digitalRead(btn_pin);
}

void cl_bounce::loop(void *func(void)) {
  if (! bounce_btn && btn != digitalRead(btn_pin)) { // если прошел фронт изм на выводн
    bounce_btn = 1;                                 // выставить флаг
    past = millis();                          // сделать временую засветку
  }
  else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
    bounce_btn = 0;      // то снять флаг
    btn_old = btn;
    btn = digitalRead(btn_pin) ; // прочитать реальное значение на выводе
    if (btn_old && ! btn) {      // если обнаружилось что это было нажатие
      func();
    }
  }
}

Ну а потом запускаешь и работает, как эта. Или не работает. Тогда ищешь в ней косяки.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

pavel747123 пишет:
Ребята подскажите как правильно паписать свою библиотеку на ардуино Я еще новичок

http://arduino.ru/Hacking/LibraryTutorial

А что, Клапауций запретил новичкам читать какие-то другие разделы сайта, кроме форума? 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

pavel747123 пишет:
Ребята подскажите как правильно паписать свою библиотеку на ардуино Я еще новичок

http://arduino.ru/Hacking/LibraryTutorial

А что, Клапауций запретил новичкам читать какие-то другие разделы сайта, кроме форума? 

Человек спросил паписать, а вы о написать, паписать это пером к предметам одушевлённым )))

pavel747123
Offline
Зарегистрирован: 10.01.2017

Извините за ошибку

pavel747123
Offline
Зарегистрирован: 10.01.2017

По этому примеру я не понимаю как писать библиотеку

У меня надо множество переменых в вести в библиотеку и отдельный цикл void

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

pavel747123 пишет:

и отдельный цикл void

Нет такого цикла... void - это спецификатор типа данных.

pavel747123
Offline
Зарегистрирован: 10.01.2017
И вот мне надо поместить цикл setup и цикл Number в библиотеку
Но незнаю как пытался по примеру не получаеться
Помогите ребята пожалуйста.
// разряд 1=13пин  разряд 2=12 разряд 3=7 разряд 4=6
int Pot=A0;
#define dataPin 10 // Контакт для подключения вывода DATA
#define latchPin 9//Контакт для подключения вывода LATCH
#define clockPin 8//Контакт для подключения вывода CLOCK
             //1  2  3   4   5   6   7  8   9  0  -  o
byte seg[] = {63,6,91,87,102,117,125,39,127,119,64,99}; //Десятичный код цыфр от 0 до 9 и точка
byte anodPin[]={13,12,7,6};
int disp =0;
void setup()
{
 
  for(int i=0;i<4;i++){
   pinMode(anodPin[i], OUTPUT);
  }
 pinMode(dataPin, OUTPUT);
 pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
 
}

void loop()
{
  int analogValue = analogRead(Pot);
   analogValue = map(analogValue,0,1023,0,9999);
  disp=analogValue;
 
  if(disp<10){
  Number(1, 10);
  Number(2, 10);
  Number(3, 10);
  Number(4, disp);
  }
  else if(disp<100){
  Number(1, 10);
  Number(2, 10);
  Number(3, disp/10);
  Number(4, disp%10);
  }
  else if(disp<1000){
  Number(1, 10);
  Number(2, disp/100);
  Number(3,(disp%100)/10);
  Number(4, disp%10);
  }
  else
  {
  Number(1, disp/1000);
  Number(2, (disp%1000)/100);
  Number(3, (disp%100)/10);
  Number(4, disp%10);
  }
}
void Number( int anNumber, int number){
     digitalWrite(latchPin,LOW);
     shiftOut(dataPin, clockPin, MSBFIRST,seg[number]);
     digitalWrite(latchPin,HIGH);
     
     int numRazryd=anodPin[anNumber-1];
     for(int i=0; i<4; i++){
      digitalWrite(anodPin[i],HIGH);
     }
     digitalWrite(numRazryd,LOW);
     delay(1);
}
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

pavel747123 пишет:

отдельный цикл void

Понятно.

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

А пока не прочитаете, лучше не трогайте цикл void. На худой конец воспользуйте функцией unsigned.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

SFU пишет:

  Как из созданной самим библитеки можно вызвать подпрограмму, которая будет реализована в основной программе? Т.е из файла моя_библиотека.ccp  сделать обращение к подпрограмме которая будет в файле моя_программа.ino ?

Показываю. class_Do_btn_deBounce.ino

/* class_Do_btn_deBounce.ino
  #1 кнопка ->2
  #2 модуль выполнения
  Принцип кода:Сделать функцию 1 по нажатию кнопки и сделать функцию 2 по отжатию кнопки
*/
//#1 кнопка
#include "Cl_Do_btn_deBounce.h"
Cl_Do_btn_deBounce Btn(2); // создать кнопку на пине 2
bool a; // переменная состояние на кнопке без дребезга
//#2 модуль выполнения
void func_1(void) {
  Serial.println("Do Func 1");
}
void func_2(void) {
  Serial.println("Do Func 2");
}
void setup() {
  //#1 кнопка
  Btn.setup();
  //#2 модуль выполнения
  Serial.begin(9600);
}
void loop() {
  //#1,#2  кнопка и модуль выполнения
  Btn.loop(& func_1, & func_2);
}

Cl_Do_btn_deBounce.h

/*Cl_Do_btn_deBounce.h
*/
#ifndef Cl_Do_btn_deBounce_h
#define Cl_Do_btn_deBounce_h

#include "Arduino.h"
class Cl_Do_btn_deBounce {
  public:
    Cl_Do_btn_deBounce(byte _pin);
    void setup();
    void loop(void (* _func_1)(), void (* _func_2)());
  private:
    byte btn_pin ;
    bool btn, btn_old;
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
};
#endif //Cl_Do_btn_deBounce_h

Cl_Do_btn_deBounce.cpp

/*Cl_Do_btn_deBounce.cpp
*/
#include "Arduino.h"
#include "Cl_Do_btn_deBounce.h"
Cl_Do_btn_deBounce::Cl_Do_btn_deBounce(byte _pin) {
  btn_pin = _pin;
}
void Cl_Do_btn_deBounce::setup() {
  pinMode(btn_pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
  btn = digitalRead(btn_pin) ; // прочитать реальное значение на выводе
}
void Cl_Do_btn_deBounce::loop(void (* _func_1)(), void (* _func_2)()) {
  if (! bounce_btn && btn != digitalRead(btn_pin)) { // если прошел фронт изм на выводн
    bounce_btn = 1;                                 // выставить флаг
    past = millis();                         // сделать временую засветку
  }
  else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
    bounce_btn = 0;      // то снять флаг
    btn_old = btn ;
    btn = digitalRead(btn_pin) ; // прочитать реальное значение на выводе
    if (btn_old && ! btn) _func_1()  ;
    if (! btn_old && btn) _func_2() ;
  }
}