初始化提交

This commit is contained in:
王立帮
2024-07-20 22:09:06 +08:00
commit c247dd07a6
6876 changed files with 2743096 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < https://docs.platformio.org/page/ci/index.html >
#
# Documentation:
#
# * Travis CI Embedded Builds with PlatformIO
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < https://docs.platformio.org/page/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
#
#
# Please choose one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
language: python
python:
- "3.6"
# Cache PlatformIO packages using Travis CI container-based infrastructure
sudo: false
cache:
directories:
- "~/.platformio"
- $HOME/.cache/pip
env:
- PLATFORMIO_CI_SRC=examples/Encoder/Encoder.ino
install:
- pip install -U platformio pip setuptools
- platformio update
script:
- platformio ci --lib="." --board=lolin32 --board=esp-wrover-kit

View File

@@ -0,0 +1,32 @@
#!/bin/bash
GITURL=$(git config --get remote.origin.url)
echo $GITURL
rm -rf html
git clone $GITURL html
cd html
if ( git checkout origin/gh-pages -b gh-pages) then
echo "Checked out $GITURL gh-pages"
else
echo "Creating out $GITURL gh-pages"
git checkout origin/master -b gh-pages
rm -r *
echo "# A simple README file for the gh-pages branch" > README.md
git add README.md
git commit -m"Replaced gh-pages html with simple readme"
git push -u origin gh-pages
fi
cd ..
doxygen doxy.doxyfile
cd html
git add *
git add search/*
git commit -a -m"updating the doxygen"
git push
cd ..
rm -rf html
git checkout master

View File

@@ -0,0 +1,27 @@
# ESP32Encoder
[![Build Status](https://travis-ci.com/madhephaestus/ESP32Encoder.svg?branch=master)](https://travis-ci.com/github/madhephaestus/ESP32Encoder)
ESP32Encoder library that uses the ESP32 pulse counter hardware peripheral:
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/pcnt.html
There is only one interrupt for the peripheral, and that is managed by the library. The user has no interrupt interface, and no interrupts are generated on each pulse. Interrupts arrive when the 16 bit counter buffer overflows, so this library has a tiny interrupt footprint while providing support for up to 10 simultaneous quadrature encoders.
# Documentation by Doxygen
[ESP32Encoder Doxygen](https://madhephaestus.github.io/ESP32Encoder/classESP32Encoder.html)
## Pull Downs/Ups
To specify the weak pull resistor set the value [useInternalWeakPullResistors](https://madhephaestus.github.io/ESP32Encoder/classESP32Encoder.html#a53dc40c9de240e90a55b427b32da451f) with the enum types [UP, DOWN, or NONE](https://madhephaestus.github.io/ESP32Encoder/ESP32Encoder_8h.html#adca399663765c125d26e6f2896b5b349)
# A note on KY-040 and similar
The "switch style" encoder wheels used by breakout modules such as:
https://usa.banggood.com/KY-040-360-Degrees-Rotary-Encoder-Module-with-1516_5mm-Potentiometer-Rotary-Knob-Cap-for-Brick-Sensor-Switch-p-1677837.html
need electrical debouncing in the range of 0.1 - 2 uf per encoder line to ground. This device bounces much more than the PCNT hardware modules debouncing time limits. Be sure to [setFilter()](https://madhephaestus.github.io/ESP32Encoder/classESP32Encoder.html#ae3cecb7d572685b3195f8a13409b3390) to 1023 as well after attaching in order to get the maximum hardware debouncing.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
#include <ESP32Encoder.h>
ESP32Encoder encoder;
ESP32Encoder encoder2;
// timer and flag for example, not needed for encoders
unsigned long encoder2lastToggled;
bool encoder2Paused = false;
void setup(){
Serial.begin(115200);
// Enable the weak pull down resistors
//ESP32Encoder::useInternalWeakPullResistors=DOWN;
// Enable the weak pull up resistors
ESP32Encoder::useInternalWeakPullResistors=UP;
// use pin 19 and 18 for the first encoder
encoder.attachHalfQuad(19, 18);
// use pin 17 and 16 for the second encoder
encoder2.attachHalfQuad(17, 16);
// set starting count value after attaching
encoder.setCount(37);
// clear the encoder's raw count and set the tracked count to zero
encoder2.clearCount();
Serial.println("Encoder Start = " + String((int32_t)encoder.getCount()));
// set the lastToggle
encoder2lastToggled = millis();
}
void loop(){
// Loop and read the count
Serial.println("Encoder count = " + String((int32_t)encoder.getCount()) + " " + String((int32_t)encoder2.getCount()));
delay(100);
// every 5 seconds toggle encoder 2
if (millis() - encoder2lastToggled >= 5000) {
if(encoder2Paused) {
Serial.println("Resuming Encoder 2");
encoder2.resumeCount();
} else {
Serial.println("Paused Encoder 2");
encoder2.pauseCount();
}
encoder2Paused = !encoder2Paused;
encoder2lastToggled = millis();
}
}

View File

@@ -0,0 +1,11 @@
name=ESP32Encoder
version=0.5.1
author=Kevin Harrington
maintainer=Kevin Harrington <mad.hephaestus@gmail.com>
sentence=Encoder library for the ESP32 using interrupts.
paragraph=Encoder library for the ESP32 using interrupts. This library supports quadrature and half quadrature.
category=Device Control
url=https://github.com/madhephaestus/ESP32Encoder/
architectures=esp32
includes=ESP32Encoder.h

View File

@@ -0,0 +1,10 @@
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
4. Redistributions of any form whatsoever must retain the following acknowledgment: 'This product includes software developed by the "Universidad de Palermo, Argentina" (http://www.palermo.edu/).'
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Standard License Header
There is no standard license header for the license

View File

@@ -0,0 +1,223 @@
/*
* ESP32Encoder.cpp
*
* Created on: Oct 15, 2018
* Author: hephaestus
*/
#include <ESP32Encoder.h>
//static ESP32Encoder *gpio2enc[48];
//
//
enum puType ESP32Encoder::useInternalWeakPullResistors=DOWN;
ESP32Encoder *ESP32Encoder::encoders[MAX_ESP32_ENCODERS] = { NULL, NULL, NULL,
NULL,
NULL, NULL, NULL, NULL };
bool ESP32Encoder::attachedInterrupt=false;
pcnt_isr_handle_t ESP32Encoder::user_isr_handle = NULL;
ESP32Encoder::ESP32Encoder() {
attached = false;
aPinNumber = (gpio_num_t) 0;
bPinNumber = (gpio_num_t) 0;
working = false;
direction = false;
unit = (pcnt_unit_t) -1;
}
ESP32Encoder::~ESP32Encoder() {
}
/* Decode what PCNT's unit originated an interrupt
* and pass this information together with the event type
* the main program using a queue.
*/
static void IRAM_ATTR pcnt_example_intr_handler(void *arg) {
ESP32Encoder * ptr;
uint32_t intr_status = PCNT.int_st.val;
int i;
for (i = 0; i < PCNT_UNIT_MAX; i++) {
if (intr_status & (BIT(i))) {
ptr = ESP32Encoder::encoders[i];
/* Save the PCNT event type that caused an interrupt
to pass it to the main program */
int64_t status=0;
if(PCNT.status_unit[i].h_lim_lat){
status=ptr->r_enc_config.counter_h_lim;
}
if(PCNT.status_unit[i].l_lim_lat){
status=ptr->r_enc_config.counter_l_lim;
}
//pcnt_counter_clear(ptr->unit);
PCNT.int_clr.val = BIT(i); // clear the interrupt
ptr->count = status + ptr->count;
}
}
}
void ESP32Encoder::attach(int a, int b, enum encType et) {
if (attached) {
Serial.println("Already attached, FAIL!");
return;
}
int index = 0;
for (; index < MAX_ESP32_ENCODERS; index++) {
if (ESP32Encoder::encoders[index] == NULL) {
encoders[index] = this;
break;
}
}
if (index == MAX_ESP32_ENCODERS) {
Serial.println("Too many encoders, FAIL!");
return;
}
// Set data now that pin attach checks are done
fullQuad = et != single;
unit = (pcnt_unit_t) index;
this->aPinNumber = (gpio_num_t) a;
this->bPinNumber = (gpio_num_t) b;
//Set up the IO state of hte pin
gpio_pad_select_gpio(aPinNumber);
gpio_pad_select_gpio(bPinNumber);
gpio_set_direction(aPinNumber, GPIO_MODE_INPUT);
gpio_set_direction(bPinNumber, GPIO_MODE_INPUT);
if(useInternalWeakPullResistors==DOWN){
gpio_pulldown_en(aPinNumber);
gpio_pulldown_en(bPinNumber);
}
if(useInternalWeakPullResistors==UP){
gpio_pullup_en(aPinNumber);
gpio_pullup_en(bPinNumber);
}
// Set up encoder PCNT configuration
r_enc_config.pulse_gpio_num = aPinNumber; //Rotary Encoder Chan A
r_enc_config.ctrl_gpio_num = bPinNumber; //Rotary Encoder Chan B
r_enc_config.unit = unit;
r_enc_config.channel = PCNT_CHANNEL_0;
r_enc_config.pos_mode = fullQuad ? PCNT_COUNT_DEC : PCNT_COUNT_DIS; //Count Only On Rising-Edges
r_enc_config.neg_mode = PCNT_COUNT_INC; // Discard Falling-Edge
r_enc_config.lctrl_mode = PCNT_MODE_KEEP; // Rising A on HIGH B = CW Step
r_enc_config.hctrl_mode = PCNT_MODE_REVERSE; // Rising A on LOW B = CCW Step
r_enc_config .counter_h_lim = _INT16_MAX;
r_enc_config .counter_l_lim = _INT16_MIN ;
pcnt_unit_config(&r_enc_config);
if (et == full) {
// set up second channel for full quad
r_enc_config.pulse_gpio_num = bPinNumber; //make prior control into signal
r_enc_config.ctrl_gpio_num = aPinNumber; //and prior signal into control
r_enc_config.unit = unit;
r_enc_config.channel = PCNT_CHANNEL_1; // channel 1
r_enc_config.pos_mode = PCNT_COUNT_DEC; //Count Only On Rising-Edges
r_enc_config.neg_mode = PCNT_COUNT_INC; // Discard Falling-Edge
r_enc_config.lctrl_mode = PCNT_MODE_REVERSE; // prior high mode is now low
r_enc_config.hctrl_mode = PCNT_MODE_KEEP; // prior low mode is now high
r_enc_config .counter_h_lim = _INT16_MAX;
r_enc_config .counter_l_lim = _INT16_MIN ;
pcnt_unit_config(&r_enc_config);
} else { // make sure channel 1 is not set when not full quad
r_enc_config.pulse_gpio_num = bPinNumber; //make prior control into signal
r_enc_config.ctrl_gpio_num = aPinNumber; //and prior signal into control
r_enc_config.unit = unit;
r_enc_config.channel = PCNT_CHANNEL_1; // channel 1
r_enc_config.pos_mode = PCNT_COUNT_DIS; //disabling channel 1
r_enc_config.neg_mode = PCNT_COUNT_DIS; // disabling channel 1
r_enc_config.lctrl_mode = PCNT_MODE_DISABLE; // disabling channel 1
r_enc_config.hctrl_mode = PCNT_MODE_DISABLE; // disabling channel 1
r_enc_config .counter_h_lim = _INT16_MAX;
r_enc_config .counter_l_lim = _INT16_MIN ;
pcnt_unit_config(&r_enc_config);
}
// Filter out bounces and noise
setFilter(250); // Filter Runt Pulses
/* Enable events on maximum and minimum limit values */
pcnt_event_enable(unit, PCNT_EVT_H_LIM);
pcnt_event_enable(unit, PCNT_EVT_L_LIM);
pcnt_counter_pause(unit); // Initial PCNT init
pcnt_counter_clear(unit);
/* Register ISR handler and enable interrupts for PCNT unit */
if(attachedInterrupt==false){
attachedInterrupt=true;
esp_err_t er = pcnt_isr_register(pcnt_example_intr_handler,(void *) NULL, (int)0,
(pcnt_isr_handle_t *)&ESP32Encoder::user_isr_handle);
if (er != ESP_OK){
Serial.println("Encoder wrap interrupt failed");
}
}
pcnt_intr_enable(unit);
pcnt_counter_resume(unit);
}
void ESP32Encoder::attachHalfQuad(int aPintNumber, int bPinNumber) {
attach(aPintNumber, bPinNumber, half);
}
void ESP32Encoder::attachSingleEdge(int aPintNumber, int bPinNumber) {
attach(aPintNumber, bPinNumber, single);
}
void ESP32Encoder::attachFullQuad(int aPintNumber, int bPinNumber) {
attach(aPintNumber, bPinNumber, full);
}
void ESP32Encoder::setCount(int64_t value) {
count = value - getCountRaw();
}
int64_t ESP32Encoder::getCountRaw() {
int16_t c;
pcnt_get_counter_value(unit, &c);
return c;
}
int64_t ESP32Encoder::getCount() {
return getCountRaw() + count;
}
int64_t ESP32Encoder::clearCount() {
count = 0;
return pcnt_counter_clear(unit);
}
int64_t ESP32Encoder::pauseCount() {
return pcnt_counter_pause(unit);
}
int64_t ESP32Encoder::resumeCount() {
return pcnt_counter_resume(unit);
}
void ESP32Encoder::setFilter(uint16_t value) {
if(value>1023)value=1023;
if(value==0) {
pcnt_filter_disable(unit);
} else {
pcnt_set_filter_value(unit, value);
pcnt_filter_enable(unit);
}
}

View File

@@ -0,0 +1,58 @@
#pragma once
#include <Arduino.h>
#include <driver/gpio.h>
#include <driver/pcnt.h>
#define MAX_ESP32_ENCODERS PCNT_UNIT_MAX
#define _INT16_MAX 32766
#define _INT16_MIN -32766
enum encType {
single,
half,
full
};
enum puType {
UP,
DOWN,
NONE
};
class ESP32Encoder {
private:
void attach(int aPintNumber, int bPinNumber, enum encType et);
boolean attached=false;
static pcnt_isr_handle_t user_isr_handle; //user's ISR service handle
bool direction;
bool working;
static bool attachedInterrupt;
int64_t getCountRaw();
public:
ESP32Encoder();
~ESP32Encoder();
void attachHalfQuad(int aPintNumber, int bPinNumber);
void attachFullQuad(int aPintNumber, int bPinNumber);
void attachSingleEdge(int aPintNumber, int bPinNumber);
int64_t getCount();
int64_t clearCount();
int64_t pauseCount();
int64_t resumeCount();
boolean isAttached(){return attached;}
void setCount(int64_t value);
void setFilter(uint16_t value);
static ESP32Encoder *encoders[MAX_ESP32_ENCODERS];
gpio_num_t aPinNumber;
gpio_num_t bPinNumber;
pcnt_unit_t unit;
bool fullQuad=false;
int countsMode = 2;
volatile int64_t count=0;
pcnt_config_t r_enc_config;
static enum puType useInternalWeakPullResistors;
};
//Added by Sloeber
#pragma once

View File

@@ -0,0 +1,40 @@
/*
* InterruptEncoder.cpp
*
* Created on: Oct 8, 2020
* Author: hephaestus
*/
#include "InterruptEncoder.h"
void IRAM_ATTR encoderAISR(void * arg) {
InterruptEncoder* object=(InterruptEncoder*)arg;
long start = micros();
long duration=start - object->microsLastA;
if (duration >= US_DEBOUNCE) {
object->microsLastA = start;
object->microsTimeBetweenTicks=duration;
object->aState = digitalRead(object->apin);
object->bState = digitalRead(object->bpin);
if (object->aState == object->bState)
object->count++;
else
object->count--;
}
}
InterruptEncoder::InterruptEncoder() {}
InterruptEncoder::~InterruptEncoder() {
if(attached)
detachInterrupt(digitalPinToInterrupt(apin));
}
int64_t InterruptEncoder::read(){
return count*2;
}
void InterruptEncoder::attach(int aPinNum, int bPinNum) {
if(attached)
return;
apin = aPinNum;
bpin = bPinNum;
pinMode(apin, INPUT_PULLUP);
pinMode(bpin, INPUT_PULLUP);
attachInterruptArg(digitalPinToInterrupt(apin), encoderAISR,this, CHANGE);
}

View File

@@ -0,0 +1,36 @@
/*
* InterruptEncoder.h
*
* Created on: Oct 8, 2020
* Author: hephaestus
*/
#ifndef INTERRUPTENCODER_H_
#define INTERRUPTENCODER_H_
#define MAX_ENCODERS 16
#define US_DEBOUNCE 10
#include <Arduino.h>
class InterruptEncoder {
private:
bool attached=false;
public:
int apin=0;
int bpin=0;
InterruptEncoder();
virtual ~InterruptEncoder();
void attach(int aPinNum, int bPinNum);
volatile bool aState=0;
volatile bool bState=0;
volatile int64_t count=0;
volatile int64_t microsLastA=0;
volatile int64_t microsTimeBetweenTicks=0;
int64_t read();
};
#endif /* INTERRUPTENCODER_H_ */