Giter Club home page Giter Club logo

Comments (44)

enesbcs avatar enesbcs commented on July 19, 2024

Where can i find instructions about creating and programming the Pro Mini? Without a working PME, i can not start even...

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Here is the sketch I use with ESPeasy

https://github.com/letscontrolit/ESPEasySlaves/tree/master/MiniProExtender

I has not been updated since long time but it works fine with esp8266 using ESPeasy software with above plugin included.

I use a custom sketch to do some extra task on Pro Mini as below.

/********************************************************************************************************************\

  • Arduino project "ESP Easy" Copyright www.esp8266.nu
  • This program is free software: you can redistribute it and/or modify it under the terms of the GNU
  • General Public License as published by the Free Software Foundation, either version 3 of the License,
  • or (at your option) any later version.
  • This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  • without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  • See the GNU General Public License for more details.
  • You received a copy of the GNU General Public License along with this program in file 'License.txt'.
  • IDE download : https://www.arduino.cc/en/Main/Software
  • ESP8266 Package : https://github.com/esp8266/Arduino
  • Source Code : https://sourceforge.net/projects/espeasy/
  • Support : http://www.esp8266.nu
  • Discussion : http://www.esp8266.nu/forum/
  • Additional information about licensing can be found at : http://www.gnu.org/licenses
    ******************************************************************************************************************/
    // This file is to be loaded onto an Arduino Pro Mini so it will act as a simple IO extender to the ESP module.
    // Communication between ESP and Arduino is using the I2C bus, so only two wires needed.
    // It is possible to run the Pro Mini on 3V3, although the 16MHz versions do not officially support this at 16MHzl
    // By working on 3.3volt you can skip levelconverters on I2C, but no guarantee that it will work stable.
    // Arduino Mini Pro uses A4 and A5 for I2C bus. ESP I2C can be configured but they are on GPIO-4 and GPIO-5 by default.

#include <Wire.h>
#include <TimerOne.h> // Avaiable from http://www.arduino.cc/playground/Code/Timer1
int triac;
int dim;
volatile int i=0; // Variable to use as a counter
volatile boolean zero_cross=0; // Boolean to store a "switch" to tell us if we have crossed zero
int triac1; // Output to Opto Triac1
int triac2; // Output to Opto Triac2
int triac3; // Output to Opto Triac3
int triac4; // Output to Opto Triac4
int triac5; // Output to Opto Triac5

//int POT_pin = A0; // Pot for testing the dimming
int LED = 13; // LED for testing
int dim1; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim2; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim3; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim4; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim5; // Dimming level (0-128) 0 = on, 128 = 0ff

int freqStep = 65; // or 78 based on power supply : This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want.
//
// The only tricky part is that the chopper circuit chops the AC wave twice per
// cycle, once on the positive half and once at the negative half. This meeans
// the chopping happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply.

// To calculate freqStep you divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps.
//
// (1000000 uS / 120 Hz) / 128 brightness steps = 65 uS / brightness step or (1000000 uS / 100 Hz) / 128 brightness steps = 78 uS / brightness step
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave or 100 Hz =

#define I2C_MSG_IN_SIZE 4
#define I2C_MSG_OUT_SIZE 4

#define CMD_DIGITAL_WRITE 1
#define CMD_DIGITAL_READ 2
#define CMD_ANALOG_WRITE 3
#define CMD_ANALOG_READ 4

volatile uint8_t sendBuffer[I2C_MSG_OUT_SIZE];
int ESPrms; // value to be sent over I2C to ESP

void setup()
{
Wire.begin(0x7f);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
//Serial.begin(9600);

pinMode(triac1, OUTPUT); // Set the Triac1 pin as output
pinMode(triac2, OUTPUT); // Set the Triac1 pin as output
pinMode(triac3, OUTPUT); // Set the Triac1 pin as output
pinMode(triac4, OUTPUT); // Set the Triac1 pin as output
pinMode(triac5, OUTPUT); // Set the Triac1 pin as output

pinMode(LED, OUTPUT); // Set the LED pin as output

attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
Timer1.initialize(freqStep); // Initialize TimerOne library for the freq we need
Timer1.attachInterrupt(dim_check, freqStep);
// Use the TimerOne Library to attach an interrupt
// to the function we use to check to see if it is
// the right time to fire the triac. This function
// will now run every freqStep in microseconds.
}

/* ******************************************************************************************************************
This part in the loop found here: [url] https://forum.arduino.cc/index.php?topic=179541.0 [/url] tnx to dc42
constant 75.7576 depends on the sensitivity of the ACS712 module
Sensitivity Min<Typ<Max mV/A
for 30A: 64< 66< 68 mV/A > constant = 5/.066 = 75.76
for 10A: 96<100<104 mV/A > constant = 5/.1 = 50.00
for 5A: 180<185<190 mV/A > constant = 5/.185 = 27.03
*/

const int currentPin = A0; // ADC pin used for ACS712

const unsigned long sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 250L; // number of samples 400 microsecond each
const unsigned long sampleInterval = sampleTime/numSamples; // sampling interval, must be longer than then ADC conversion time
int adc_zero = 514; // relative zero of the ACS712 for me 514 was best. 511
int valueRead; // value read on ADC

void zero_cross_detect() {
zero_cross = true; // set the boolean to true to tell our dimming function that a zero cross has occured
i=0;
// since the control pin stays high, the TRIAC won't 'unlatch'
// when zero-crossing, so I need to put the pins to LOW
digitalWrite(triac1, LOW);
digitalWrite(triac2, LOW);
digitalWrite(triac3, LOW);
digitalWrite(triac4, LOW);
digitalWrite(triac5, LOW);

// writing pins is like 10 times faster if
// we write the register directly
// instead of using 'digitalWrite'

}

// Turn on the TRIAC at the appropriate time
void dim_check() {
if(zero_cross == true) {

if(i>=dim1)  {                     
  digitalWrite(triac1, HIGH);  // turn on triac1
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   
                       
 if(i>=dim2) {                     
  digitalWrite(triac2, HIGH);  // turn on triac2 
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   
           
   
  if(i>=dim3) {                     
  digitalWrite(triac3, HIGH);  // turn on triac3
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   


 if(i>=dim4) {                     
  digitalWrite(triac4, HIGH);  // turn on triac4
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   


if (i>=dim5) {                     
  digitalWrite(triac5, HIGH);  // turn on triac5
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}    
else {
  
  i++; // increment time step counter 

}
 
                  
}                                

}

void loop()

{

     if (triac == 4) {
        dim1 = dim / 8;
         
      }
     if (triac == 5) {
        dim2 = dim / 8; 
      }

      if (triac == 6) {
        dim3 = dim / 8; 
      }
     if (triac == 7) {
        dim4 = dim / 8; 
      }

     if (triac == 8) {
        dim5 = dim / 8; 
      }

//dim = dim / 8; // set dimmer value to global integer dim
//dim = analogRead(POT_pin) / 8; // read dimmer value from potentiometer
//analogWrite(LED, dim); // write dimmer value to the LED, for debugging

/*
Serial.print(dim);
Serial.print("dim = ");
Serial.print("triac = ");
Serial.print(triac);
Serial.print("dim1 = ");
Serial.print(dim1);

Serial.print("triac1 = ");

Serial.print(triac1);
Serial.print("dim2 = ");
Serial.print(dim2) ;
Serial.print("triac2 = ");
Serial.print(triac2);
Serial.print("dim3 = ");
Serial.print(dim3);
Serial.print("triac3 = ");
Serial.print(triac3);
Serial.print("dim4 = ");
Serial.print(dim4);
Serial.print("triac4 = ");
Serial.print(triac4);
Serial.print("ESPrms = ");
Serial.print(ESPrms);

delay(1000);
Serial.print('\n');

unsigned long currentAcc = 0;
unsigned int count = 0;
unsigned long prevMicros = micros() - sampleInterval ;

while (count < numSamples)

{
if (micros() - prevMicros >= sampleInterval)
{
long adc_raw = analogRead(currentPin) - adc_zero;
currentAcc += (unsigned long)(adc_raw * adc_raw);
++count;
prevMicros += sampleInterval;
}
}

float rms = sqrt((float)currentAcc/(float)numSamples) * (27.03 / 1024.0); // see note above for this 27.03 value
ESPrms = 1000*rms; // conversion of float Ampere into integer milliAmpere needed for I2C communication

/
}
/
****************************************************************************************************************** */

void receiveEvent(int count)
{
if (count == I2C_MSG_IN_SIZE)
{
byte cmd = Wire.read();
byte port = Wire.read();
int value = Wire.read();
value += Wire.read()*256;
switch(cmd)
{
case CMD_DIGITAL_WRITE:
pinMode(port,OUTPUT);
digitalWrite(port,value);
break;
case CMD_DIGITAL_READ:
pinMode(port,INPUT_PULLUP);
clearSendBuffer();
sendBuffer[0] = digitalRead(port);
break;
case CMD_ANALOG_WRITE:
//analogWrite(port,value);
triac=(port);
if (port == 4) triac1 = (port);
if (port == 5) triac2 = (port);
if (port == 6) triac3 = (port);
if (port == 7) triac4 = (port);
if (port == 8) triac5 = (port);
dim=(value);
//dim=dim / 8;
//if (port == 4) dim1 = (value);
// if (port == 5) dim2 = (value);
// if (port == 6) dim3 = (value);
// if (port == 7) dim4 = (value);
// if (port == 8) dim5 = (value);
break;
case CMD_ANALOG_READ:
clearSendBuffer();
if (port <= 4) valueRead = analogRead(port); // port <=4 to read analog value A0,A1,A2,A3 - A4 & A5 are I2C
if (port == 100) valueRead = ESPrms; // port is any number >4 up to 255
//if (port == 2) selector = analogRead(A2);
//if (port == 3) level = analogRead(A3);
sendBuffer[0] = valueRead & 0xff;
sendBuffer[1] = valueRead >> 8;
break;
}
}
}

void clearSendBuffer()
{
for(byte x=0; x < sizeof(sendBuffer); x++)
sendBuffer[x]=0;
}

void requestEvent()
{
Wire.write((const uint8_t*)sendBuffer,sizeof(sendBuffer));
}

from rpieasy.

happytm avatar happytm commented on July 19, 2024

As you can see I am using Pro Mini for Mains current measurement and AC dimmer control which are impossible using only RPI or ESP8266.
That is the importance of including Pro Mini. Only requirement is communication going between RPI and Pro Mini via I2C bus.

Thanks

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I found this on ebay, according to its description it is an AT Mega328 3.3V compatible with Pro Mini, i can order this if it will be sufficient to test:
https://www.ebay.com/itm/Mini-ATMEAG328-3-3V-8Mhz-Replace-ATmega128-for-Arduino-Pro-Mini-Compatible/173360751835
Otherwise I2C is not a big deal, but the ESPEasy plugin that handles the Pro Mini looks like a little complicated to me, it will not be easy to port it. Sending commands to the Pro Mini may be implemented, but for the reverse way (from ProMini to RPIEasy) currently i have no clue how to store/display data...

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I followed user Costo's post on ESPeasy forum to understand how to read values from Pro Mini into ESPeasy. Basically he set up devices in ESPeasy on devices tab to read value from Pro Mini.Link is below

https://www.letscontrolit.com/forum/viewtopic.php?f=4&t=627&p=6385&hilit=pme#p6385

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

So basically we can use Dummy devices to hold values and create one (or more) ProMini devices, in which to be given the destination task and value number(s) (max 10 row per dev?) with type (analog/digital)? I've done something similar (value rerouting) with battery value watching, which can be setted in Advanced settings. (i am using an ADS1015 for this goal now)

The "compatible" device i mentioned in the previous post is right?

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Yes device you chose should work fine. For that matter any arduino device should work fine with shift register for 5V device or directly without shift register for 3.3V device. Your device is 3.3V so it should be fine by connecting directly 4 wires (3.3V, GND, SCL & SDA).To store value to dummy device you can use rules if it is implemented in your code.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

You will also need FTDI adapter to upload the sketch to Pro Mini like below

https://www.ebay.com/itm/FT232RL-FTDI-Serials-Adapter-Module-Mini-Port-f-USB-to-TTL-3-3V-5-5V-BBC/142727421107?hash=item213b379cb3:g:EKMAAOSwinVZtzmB:rk:1:pf:0

Arduino Uno has this usb to serial chip built in but Pro mini does not.

I live in USA and if you need Pro Mini , FTDI adapter and some extra sensors I have I can send them to you. Please let me know.

Thanks

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Thanks, but I already have a CP2102 (for flashing Sonoff devices) i think it will work for uploading, and ordered a ProMini for testing. Itt will arrive in time.. If you want to send some other sensors which is currenty not supported, itt will be nice.. but i am living in Hungary, Europe. :)

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I was reading and tried to interpret the PME code. But i found a possible issue: It's default address 0x7f is outside of the valid I2C range. (0x08-0x77)
https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing
I doubt that RPI smbus module will handle it.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Is it not possible to define different address within the range (0x008-0x77) in PME plugin and match same newly defined address in pro mini extender code on arduino ? While searching web I found following links

https://www.raspberrypi.org/forums/viewtopic.php?t=155389
https://www.raspberrypi.org/forums/viewtopic.php?t=170958
https://oscarliang.com/raspberry-pi-arduino-connected-i2c/ (using 0x04 address)
https://www.bluetin.io/interfacing/i2c-connect-raspberry-pi-arduino/ (using 0x08 address)

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Yes, it is absolutely possible, but every PME needs to be reflashed with the recompiled sketch. :) I prefer 0x3F for the new address as this is the valid counterpart for 0x7f in 7bit.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Thank you for start on PME plugin. Can't wait to test once it is implemented.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Experimental version added at b0ca949

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I started testing this plugin and following is my feedback -

  • I tested both standard address 0x3f & non standard address 0x7f and both seems to communicate with
    pro mini so that was very good start.

  • I then attached joystick to analog pin 6 & 7 & switch part of joystick to digital pin 9 of pro mini and set up 3 different devices on device page to read value from each of 3 pins it send values but they are all same value and not different value.It should be different value for each of 3 pins. following is log -

When joystick down -

22:27:46 Event: PMEanalog6#Value=0.0
22:27:46 Event: PMEanalog7#Value=0.0
22:27:47 Event: PMEdigital9#Value=0.0

When joystick in middle -

22:27:50 Event: PMEdigital9#Value=255.0
22:27:50 Event: PMEanalog6#Value=511.0
22:27:50 Event: PMEanalog7#Value=511.0

When joystick up -

22:27:55 Event: PMEanalog6#Value=1023.0
22:27:55 Event: PMEanalog7#Value=1023.0
22:27:56 Event: PMEdigital9#Value=255.0

22:28:00 Event: Clock#Time=Thu,22:28

  • When switch pressed on joystick for few seconds -

22:31:52 Event: PMEdigital9#Value=149.0
22:31:52 Event: PMEanalog6#Value=405.0
22:31:52 Event: PMEanalog7#Value=405.0
22:31:53 Event: PMEdigital9#Value=162.0
22:31:53 Event: PMEanalog6#Value=418.0
22:31:53 Event: PMEanalog7#Value=418.0
22:31:54 Event: PMEdigital9#Value=160.0
22:31:54 Event: PMEanalog7#Value=416.0
22:31:54 Event: PMEanalog6#Value=416.0
22:31:55 Event: PMEdigital9#Value=158.0
22:31:55 Event: PMEanalog6#Value=414.0
22:31:55 Event: PMEanalog7#Value=414.0
22:31:56 Event: PMEdigital9#Value=158.0
22:31:56 Event: PMEanalog7#Value=414.0
22:31:56 Event: PMEanalog6#Value=414.0
22:31:57 Event: PMEdigital9#Value=148.0
22:31:57 Event: PMEanalog6#Value=404.0
22:31:57 Event: PMEanalog7#Value=404.0
22:31:58 Event: PMEdigital9#Value=110.0
22:31:58 Event: PMEanalog6#Value=366.0
22:31:58 Event: PMEanalog7#Value=366.0
22:31:59 Event: PMEdigital9#Value=138.0
22:31:59 Event: PMEanalog6#Value=138.0
22:31:59 Event: PMEanalog7#Value=138.0
22:32:00 Event: PMEdigital9#Value=99.0
22:32:00 Event: PMEanalog6#Value=355.0
22:32:00 Event: PMEanalog7#Value=355.0
22:32:00 Event: Clock#Time=Thu,22:32
22:32:02 Event: PMEdigital9#Value=99.0
22:32:02 Event: PMEanalog6#Value=355.0
22:32:02 Event: PMEanalog7#Value=355.0
22:32:03 Event: PMEdigital9#Value=101.0
22:32:03 Event: PMEanalog6#Value=357.0
22:32:03 Event: PMEanalog7#Value=357.0
22:32:04 Event: PMEdigital9#Value=101.0
22:32:04 Event: PMEanalog6#Value=357.0
22:32:04 Event: PMEanalog7#Value=357.0
22:32:05 Event: PMEdigital9#Value=106.0
22:32:05 Event: PMEanalog6#Value=362.0
22:32:05 Event: PMEanalog7#Value=362.0
22:32:06 Event: PMEdigital9#Value=111.0
22:32:06 Event: PMEanalog6#Value=367.0
22:32:06 Event: PMEanalog7#Value=367.0
22:32:07 Event: PMEdigital9#Value=120.0
22:32:07 Event: PMEanalog6#Value=376.0
22:32:07 Event: PMEanalog7#Value=376.0
22:32:08 Event: PMEdigital9#Value=120.0
22:32:08 Event: PMEanalog6#Value=376.0
22:32:08 Event: PMEanalog7#Value=376.0
22:32:09 Event: PMEdigital9#Value=120.0
22:32:09 Event: PMEanalog6#Value=376.0
22:32:09 Event: PMEanalog7#Value=376.0
22:32:10 Event: PMEdigital9#Value=127.0
22:32:10 Event: PMEanalog6#Value=383.0
22:32:10 Event: PMEanalog7#Value=383.0
22:32:11 Event: PMEdigital9#Value=127.0
22:32:11 Event: PMEanalog6#Value=383.0
22:32:11 Event: PMEanalog7#Value=383.0
22:32:12 Event: PMEdigital9#Value=127.0
22:32:12 Event: PMEanalog6#Value=383.0
22:32:12 Event: PMEanalog7#Value=383.0
22:32:13 Event: PMEdigital9#Value=126.0
22:32:13 Event: PMEanalog6#Value=382.0
22:32:13 Event: PMEanalog7#Value=382.0
22:32:14 Event: PMEdigital9#Value=127.0
22:32:14 Event: PMEanalog6#Value=383.0
22:32:14 Event: PMEanalog7#Value=383.0
22:32:15 Event: PMEdigital9#Value=126.0
22:32:15 Event: PMEanalog6#Value=382.0
22:32:15 Event: PMEanalog7#Value=382.0
22:32:16 Event: PMEdigital9#Value=126.0
22:32:16 Event: PMEanalog6#Value=382.0
22:32:16 Event: PMEanalog7#Value=382.0
22:32:17 Event: PMEdigital9#Value=231.0
22:32:17 Event: PMEanalog6#Value=231.0
22:32:17 Event: PMEanalog7#Value=231.0

If I move joystick sideways on both ends it seems there is no effect and values in log remain same as if joystick is middle position.

For output side if at least 1 device is enabled (for reading pin value from pro mini ) then both extpwm & extgpio works fine and turn pin high or low when I issue extpwm or extgpio command from advanced tab of rpieasy. But in original espeasy there was no need to set up pme plugin on device page in order to enable extgpio and extpwm command. Output side worked automatically without setting up anything on device page for pme plugin.

It is very good start and I appreciate your efforts.

Thanks

from rpieasy.

happytm avatar happytm commented on July 19, 2024

On further testing I realised that I was using 1 second interval on device page for all 3 pins so i changed interval to 2 seconds on 2 analog pins ( analog 6 & analog 7 ) and then it works reliably as it should. For digital pin 9 on pro mini no matter what interval I set on device page it shows value of 255 but it should be 1 or 0. sorry for confusion. Is it possible to change this behavior so that when switch is pressed or released on pin 9 it send data instantly to rpi instead of waiting for 60 seconds ?

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Thanks for testing.
In RPIEasy, it will sure commands will remain at their specific plugins, so you have activate "Switch" plugin to use gpio and MCP plugin to use extgpio.. for the same reason you have to activate USBRelay plugin to use usbrelay command, and PyGame Sound Player for playaudio command, etc, etc..
The reason is simple: RPIEasy can be run on machines, that do not have GPIO support, for example i running it at my PC also with Ubuntu. And i think every plugin has it's specific task, for good reason.

I am not familiar with the Arduino side of the ProMini, pin number 9 is just forwarded as it written in the text box to the ProMini.
As i see the promini code is not capable of sending any data without receiving a read command, so i do not know, how to achieve instantous feedbacks from gpio changes. Is that function works on ESPEasy plugin? Maybe i can send several read commands per second, for ex 10 times per second. Or a new function has to be coded to the promini, that registers attachInterrupt() handler with the selected port and sends data accordingly.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Thank you for your clarification on switch plugin. I will have to test more to see if there can be something done on pro mini code.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

@happytm:
Could you try the new plugin? 7373154
Please delete PME devices, than recreate, and set Interval to 0. In this mode plugin asks the selected pin status ten times per second, and if state is changed, than event is fired. Warning: In this mode, i measured approximately +4% CPU usage/pin! So only use, if it is crucial. I tested 1 second interval with two pin and i do not found any problem, and cpu usage is minimal in this mode. (yet) With analog values it will be very noisy, for digital inputs, it could be handy.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I tried new plugin -

  • digital pin connected to switch now works instantly without any problem.
  • analog pins connected to joystick and interval set at 0 in plugin does not respond in log at all when changing joystick position. So I tried different interval from 1 second to 5 seconds and it respond with joystick activity but it shows exact same value for both.Before this commit it was working ok and showing separate values from 2 pins with 2 second interval in plugin.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I guess that analog readings takes more time at the ProMini side, and i have to set delay back to 0.01s. (if data not arrived or arrived a lot of zeros, than it is not a changing and with Interval 0 only the changes logged)
On the other hand, digital reads are almost instantous so i left it at 0.001s. I doubt that analog reading is possible with this device at a faster speed. Is it faster with ESP8266?
Updated on github.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

With esp8266 there are problems with RAM & load so it seems faster some times and it is very slow on other times.Compared to that I feel Rpieasy is way faster.There is too much going on there in the code frequently so reliability is not the best. That is the reason I want to move my projects on Rpieasy platform.Plus I can use RPI for lot of other things like audio, video etc. Analog on promini is something I do not use except to read current sensor ACS712 but I do not need very fast data update for that.I was using joystick to just test the plugin.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I see. Could you test the latest update? I hope it fixes analog result mixing.

RPIEasy is still a beta version, and you have to consider the SD card wear leveling problem, when migrating projects to it. But it is really useful if you want some other things like online radio, usb dvb tv, etc. For analog measuring i am using 4 channel ADS1015.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

It did not change duplicate values problem. I tried sending data from pro mini in different ways but no success.I created separate integers in pro mini for each pin and sent 7 integers to rpieasy but somehow with every 2 second interval (which I set in plugin ) value becomes same even though when I print those integers values in serial monitor on pro mini it shows separate values for each analog pin correctly.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Seems really odd, tried to use a semaphore to not mix results.
RPIEasy uses threading by design to run plugin_read commands to speed things up, so it can happen that an analogread command interrupts an other one's response. (ESPEasy is single threaded so it is not a problem there)
dce3e3c
If latest commit not helps, than i have to extend the arduino sketch to include pin number in the response packet, this is the only way we can sure that results do not mix anymore.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Whatever you did with this commit it seems duplicate values from pro mini no longer happening. I used joystick to test (using 2 seconds interval in plugin for both pins) and it brings separate values from both pins based on real activity of joystick. Thank you.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

you are welcome. in theory 1 seconds interval might work also.
if this operation is adequate, can this issue be closed?

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Spoke too soon. it seems like it behaves like before after few minutes.But if I reset pro mini it works properly for few minutes again and same pattern again. May be I2C looses connection and mess up everything.Regarding 1 second interval I tried 1 second interval on both pins but only 1 pin result shows up in log and that too is frozen so it does not respond to joystick anymore and second pin result disappears. strange behavior on 1 second interval. the log is below with comments:

01:07:38 Event: analog6#Value=511.0 // problem starts
01:07:39 Event: analog7#Value=511.0
01:07:40 Event: analog6#Value=511.0
01:07:41 Event: analog7#Value=511.0
01:07:42 Event: analog6#Value=511.0
01:07:43 Event: analog7#Value=511.0
01:07:44 Event: analog6#Value=511.0
01:07:45 Event: analog7#Value=511.0
01:07:46 Event: analog6#Value=511.0
01:07:47 Event: analog7#Value=511.0
01:07:48 Event: analog6#Value=511.0
01:07:49 Event: analog7#Value=511.0
01:07:50 Event: analog6#Value=511.0
01:07:51 Event: analog7#Value=511.0
01:07:52 Event: analog6#Value=511.0
01:07:53 [Errno 121] Remote I/O error // pro mini reset by me manually
01:07:54 [Errno 121] Remote I/O error
01:07:55 [Errno 121] Remote I/O error
01:07:56 Event: analog6#Value=507.0 // from here works fine until automatic reset
01:07:57 Event: analog7#Value=511.0
01:07:58 Event: analog6#Value=507.0
01:07:59 Event: analog7#Value=511.0
01:08:00 Event: analog6#Value=507.0
01:08:00 Event: Clock#Time=Wed,01:08
01:08:01 Event: analog7#Value=511.0
01:08:02 Event: analog6#Value=507.0
01:08:03 Event: analog7#Value=511.0
01:08:04 Event: analog6#Value=507.0
01:08:05 Event: analog7#Value=511.0
01:08:06 Event: analog6#Value=507.0
01:08:07 Event: analog7#Value=511.0
01:08:09 Event: analog6#Value=507.0
01:08:10 Event: analog7#Value=511.0
01:08:11 Event: analog6#Value=507.0
01:08:12 Event: analog7#Value=511.0
01:08:13 Event: analog6#Value=507.0
01:08:14 Event: analog7#Value=511.0
01:08:15 Event: analog6#Value=507.0
01:08:16 Event: analog7#Value=511.0
01:08:17 Event: analog6#Value=507.0
01:08:18 Event: analog7#Value=511.0
01:08:19 [Errno 121] Remote I/O error //automatic reset
01:08:20 Event: analog7#Value=511.0 // problem starts again
01:08:21 Event: analog6#Value=511.0
01:08:22 Event: analog7#Value=511.0
01:08:23 Event: analog6#Value=511.0

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I found this hint: "if the Master runs too fast and sends another Wire.beginTransmission() before the last read is complete, this can lead to communications bind up as the prior event onReceive() did not complete its work and possibly corrupting the current transmission in progress."
I have to rethink I2C usage in RPIEasy. Other plugins are not so affected , but with multiple PME device started with several thread paralell needs a more exact timing and maybe some global I2C handler. Work in progress.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Please try commit 36f9a87
I2C queueing implemented to avoid value mixing and i2c grabbing by one plugin. Runned for several minutes without errors, but needs further testing. If ProMini suddenly stops responding, than try to modify line 79 in rpiwire.py from:
time.sleep(0.02)
to
time.sleep(0.08)
than remove power from it and reconnect. May be a timing issue, but can also be a buffer overflow error at the Arduino sketch of the ProMini. (I've got a package full of 0xFF bytes from the ProMini right before the same values began to arrive)

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I tested it and it is working better than before.It lasted 1 hour this time before automatic reset.I think you can close the issue at this time and in future you can try it yourself or some one else with promini and joystick.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Thank you very much, your package arrived to me today, and it contains ProMini and joystick also (among many other stuff), so i can do more tests. :)
I am not sure if it is a reset on the ProMini, as hardware reset solves the problem, instead seems to be a lock-up.. which can be solved with a Watchdog i think.
Did you use the joystick with direct connection with a 3V ProMini or it needs a Level Shifter between the two?

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I used joystick directly because pro mini i always use is 3.3v version (8mhz) the one I sent you is 3.3v so no need to have level shifter. The programming board also is set on 3.3v via jumper. I do not populate 6 pins on edge of pro mini to program it but just use holes and hold it tight with ftdi adapter while loading the program and it works. For my tests I used analog pins A6 & A7 for joystick.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Thanks! I rewrite the MiniProExtender sketch, relocated the slow analogread() function from the ISR into the loop, i will test it with the joystick and let you know the results.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I think with commit e2eebc4 i reached end of the road. There are nothing more i can do with the original PME sketch, approximately 1hour of continous reading can be achieved maximum, before PME I2C receiver function fails, and only power cycling can fix it.
So i've done a boosted sketched that can be downloaded here: https://github.com/enesbcs/ESPEasySlaves/blob/master/MiniProExtender/MiniProExtender.ino
With the new sketch it is working continously for 3hours now, without error. Tested with an analog joystick (2 analog port, 1 digital, reading interval=0 all of them)

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Thank you for all your efforts on this plugin. I tested it last night for few hours and it was working finefor general input output control from rpieasy. I still will be using original sketch from espeasy for my project with your original plugin from few days ago that was working fine except analog read which I do not need.My project need to control 6 digital pins on promini and I am not controlling it directly but sending extpwm commands for each 6 pins of promini via rules and at pro mini I am storing it into 7 integers (1 for pin number & 6 integers for pwm values to further process in a sketch on promini without triggering pins at pro mini. like below:

case CMD_ANALOG_WRITE:
//analogWrite(port,value);
triac=(port);
if (port == 4) triac1 = (port);
if (port == 5) triac2 = (port);
if (port == 6) triac3 = (port);
if (port == 7) triac4 = (port);
if (port == 8) triac5 = (port);
if (port == 9) triac6 = (port);
dim=(value);

I tried to store values to integers from your new pro mini sketch but I was unable to do so.

At some point you can look into serial interface to pro mini instead of using I2C. I am not sure there is any code in espeasy for that.

Thanks again.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

The serial plugin is also under development, i ran some multithreading related problems with that. I will try the analog_write hacking, if analog_write worked previously than this also hast to work. But your sketch in the first post will not work in this form, than it contains a delay() in the loop section, which will effectively kill the whole I2C processing.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

Oh that's a good news.
Thank you.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Could you send the sketch you are using, without the unnecessary portions/comments? The one that you included in the first post, has some errors with comments and something is missing, as number of "}" is not ok. The section that calculates ESPrms is commented out, isn't it necessary?
This sketch is a bit cryptic to me, triac1..triac5 has no initial value as i see, but despite it, in the setup field this values used as pin numbers.. there are no way, that anything executed before setup() that assign values to them.

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I am sorry I am not a programmer so I must have messed up somewhere. but following is user Costo's original sketch I am trying to use for promini:

/********************************************************************************************************************\

  • Arduino project "ESP Easy" Copyright www.esp8266.nu
  • This program is free software: you can redistribute it and/or modify it under the terms of the GNU
  • General Public License as published by the Free Software Foundation, either version 3 of the License,
  • or (at your option) any later version.
  • This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  • without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  • See the GNU General Public License for more details.
  • You received a copy of the GNU General Public License along with this program in file 'License.txt'.
  • IDE download : https://www.arduino.cc/en/Main/Software
  • ESP8266 Package : https://github.com/esp8266/Arduino
  • Source Code : https://sourceforge.net/projects/espeasy/
  • Support : http://www.esp8266.nu
  • Discussion : http://www.esp8266.nu/forum/
  • Additional information about licensing can be found at : http://www.gnu.org/licenses
    ******************************************************************************************************************/
    // This file is to be loaded onto an Arduino Pro Mini so it will act as a simple IO extender to the ESP module.
    // Communication between ESP and Arduino is using the I2C bus, so only two wires needed.
    // It is possible to run the Pro Mini on 3V3, although the 16MHz versions do not officially support this at 16MHzl
    // By working on 3.3volt you can skip levelconverters on I2C, but no guarantee that it will work stable.
    // Arduino Mini Pro uses A4 and A5 for I2C bus. ESP I2C can be configured but they are on GPIO-4 and GPIO-5 by default.

#include <Wire.h>

#define I2C_MSG_IN_SIZE 4
#define I2C_MSG_OUT_SIZE 4

#define CMD_DIGITAL_WRITE 1
#define CMD_DIGITAL_READ 2
#define CMD_ANALOG_WRITE 3
#define CMD_ANALOG_READ 4

volatile uint8_t sendBuffer[I2C_MSG_OUT_SIZE];
int ESPrms; // value to be sent over I2C to ESP

void setup()
{
Wire.begin(0x7f);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}

/* ******************************************************************************************************************
This part in the loop found here: [url] https://forum.arduino.cc/index.php?topic=179541.0 [/url] tnx to dc42
constant 75.7576 depends on the sensitivity of the ACS712 module
Sensitivity Min<Typ<Max mV/A
for 30A: 64< 66< 68 mV/A > constant = 5/.066 = 75.76
for 10A: 96<100<104 mV/A > constant = 5/.1 = 50.00
for 5A: 180<185<190 mV/A > constant = 5/.185 = 27.03
*/

const int currentPin = A7; // ADC pin used for ACS712
const unsigned long sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 250L; // number of samples 400 microsecond each
const unsigned long sampleInterval = sampleTime/numSamples; // sampling interval, must be longer than then ADC conversion time
int adc_zero = 514; // relative zero of the ACS712 for me 514 was best. 511
int valueRead; // value read on ADC

void loop()
{
unsigned long currentAcc = 0;
unsigned int count = 0;
unsigned long prevMicros = micros() - sampleInterval ;

while (count < numSamples)
{
if (micros() - prevMicros >= sampleInterval)
{
long adc_raw = analogRead(currentPin) - adc_zero;
currentAcc += (unsigned long)(adc_raw * adc_raw);
++count;
prevMicros += sampleInterval;
}
}

float rms = sqrt((float)currentAcc/(float)numSamples) * (27.03 / 1024.0); // see note above for this 27.03 value
ESPrms = 1000rms; // conversion of float Ampere into integer milliAmpere needed for I2C communication
}
/
*******************************************************************************************************************

void receiveEvent(int count)
{
if (count == I2C_MSG_IN_SIZE)
{
byte cmd = Wire.read();
byte port = Wire.read();
int value = Wire.read();
value += Wire.read()*256;
switch(cmd)
{
case CMD_DIGITAL_WRITE:
pinMode(port,OUTPUT);
digitalWrite(port,value);
break;
case CMD_DIGITAL_READ:
pinMode(port,INPUT_PULLUP);
clearSendBuffer();
sendBuffer[0] = digitalRead(port);
break;
case CMD_ANALOG_WRITE:
analogWrite(port,value);
break;
case CMD_ANALOG_READ:
clearSendBuffer();
if (port <= 4) valueRead = analogRead(port); // port <=4 to read analog value A0,A1,A2,A3 - A4 & A5 are I2C
if (port == 100) valueRead = ESPrms; // port is any number >4 up to 255
sendBuffer[0] = valueRead & 0xff;
sendBuffer[1] = valueRead >> 8;
break;
}
}
}

void clearSendBuffer()
{
for(byte x=0; x < sizeof(sendBuffer); x++)
sendBuffer[x]=0;
}

void requestEvent()
{
Wire.write((const uint8_t*)sendBuffer,sizeof(sendBuffer));
}

Also for AC dimmers I wanted to use this original sketch which is below.I was trying to use input from RPIEasy and save it into integers at pro mini and then use those values to fire triacs. :

/*
AC Light Control

Ryan McLaughlin [email protected]

The hardware consists of an Triac to act as an A/C switch and
an opto-isolator to give us a zero-crossing reference.
The software uses two interrupts to control dimming of the light.
The first is a hardware interrupt to detect the zero-cross of
the AC sine wave, the second is software based and always running
at 1/128 of the AC wave speed. After the zero-cross is detected
the function check to make sure the proper dimming level has been
reached and the light is turned on mid-wave, only providing
partial current and therefore dimming our AC load.

Thanks to http://www.andrewkilpatrick.org/blog/?page_id=445
and http://www.hoelscher-hi.de/hendrik/english/dimmer.htm
*/

/*
Modified by Mark Chester [email protected]

to use the AC line frequency (half-period) as a reference point
and fire the triacs based on that plus a count of dimming steps.
Tracks the line frequency and adjusts accordingly. Can set up to
an estimated 512 steps of dimmer resolution.

*/
#include <Wire.h>
#include <TimerOne.h> // http://www.arduino.cc/playground/Code/Timer1

int dim1; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim2; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim3; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim4; // Dimming level (0-128) 0 = on, 128 = 0ff
//int dim5; // Dimming level (0-128) 0 = on, 128 = 0ff

int triac1; // Output to Opto Triac1
int triac2; // Output to Opto Triac2
int triac3; // Output to Opto Triac3
int triac4; // Output to Opto Triac4
//int triac5; // Output to Opto Triac5

// General
unsigned long int ZeroXTime[4] = {0,0,0,0}; // Timestamp in micros() of the zero crossing interrupts
unsigned long int DimStep; // How many micros() in each step of dimming
unsigned long int AvgPeriod; // The average line voltage period in micros()
unsigned long int PeriodResync = 3000; // Number of milliseconds between line freq measurements
unsigned long int ResetPeriod = PeriodResync; // The timestamp in millis() when we will measure the period again
unsigned long int DimRes = 256; // How many steps of dimmer resolution
volatile unsigned long int DimStepCounter; // For counting Timer1 interrupts
volatile unsigned long int FireTriac[4] = {0,0,0,0}; // When it's OK to fire the triacs, in counts of DimRes
volatile boolean zero_cross = 0; // Tels us we've crossed the zero line
//byte TriacPin[4] = {4,5,6,7}; // Which digital IO pins to use
byte TriacPin[4] = {triac1,triac2,triac3,triac4}; // Which digital IO pins to use

#define I2C_MSG_IN_SIZE 4
#define I2C_MSG_OUT_SIZE 4

#define CMD_DIGITAL_WRITE 1
#define CMD_DIGITAL_READ 2
#define CMD_ANALOG_WRITE 3
#define CMD_ANALOG_READ 4

volatile uint8_t sendBuffer[I2C_MSG_OUT_SIZE];

void setup() { // Begin setup
Wire.begin(0x3f);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Timer1.initialize(DimStep); // Start up the Timer1 timer
attachInterrupt(0, zero_cross_detect, FALLING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
pinMode(triac1, OUTPUT); // Set the Triac pin as output
pinMode(triac2, OUTPUT); // Set the Triac pin as output
pinMode(triac3, OUTPUT); // Set the Triac pin as output
pinMode(triac4, OUTPUT); // Set the Triac pin as output
measure_half_period(); // Initially measure the half period
} // End setup

void measure_half_period() {
zero_cross = 0; // Clearing this here increases the accuracy of the measurement
byte F = 0; // Frequency counter counter ;)
while ( F < 4 ) { // This loop takes 4 zero cross samples
if ( zero_cross ) { // Only run if a zero cross is detected
ZeroXTime[F] = micros(); // Set the new current zero cross time in micros()
zero_cross = 0; // Reset zero_cross
F++; // Bump the counter for the next sample
}
} // Now we calc the length of each DimStep
DimStep = (((ZeroXTime[1]-ZeroXTime[0]) + (ZeroXTime[2]-ZeroXTime[1]) + (ZeroXTime[3]-ZeroXTime[2])) / 3) / DimRes;
Timer1.attachInterrupt(fire_triacs, DimStep); // (Re)Associate fire_triacs() with the Timer1 interrupt and the latest DimStep period
ResetPeriod = ResetPeriod + PeriodResync; // Set the next time when we'll measure the half period again
}

void zero_cross_detect() { // function to be fired at the zero crossing
zero_cross = 1; // set a variable that's picked up later
DimStepCounter = 0; // Reset the step counter for the next round of triac firings
}

void fire_triacs() { // Called every DimStep (Timer1 interrupt, checks FireTriac[n] and fires if it's time
if ( FireTriac[0] == DimStepCounter ) { // Is it time to fire?
digitalWrite(triac1, HIGH); // Fire the Triac mid-phase
delayMicroseconds(2);
digitalWrite(triac1, LOW); // Turn off the Triac gate (Triac will not turn off until next zero cross)
}
if ( FireTriac[1] == DimStepCounter ) { // Is it time to fire?
digitalWrite(triac2, HIGH); // Fire the Triac mid-phase
delayMicroseconds(2);
digitalWrite(triac2, LOW); // Turn off the Triac gate (Triac will not turn off until next zero cross)
}
if ( FireTriac[2] == DimStepCounter ) { // Is it time to fire?
digitalWrite(triac3, HIGH); // Fire the Triac mid-phase
delayMicroseconds(2);
digitalWrite(triac3, LOW); // Turn off the Triac gate (Triac will not turn off until next zero cross)
}
if ( FireTriac[3] == DimStepCounter ) { // Is it time to fire?
digitalWrite(triac4, HIGH); // Fire the Triac mid-phase
delayMicroseconds(2);
digitalWrite(triac4, LOW); // Turn off the Triac gate (Triac will not turn off until next zero cross)
}
DimStepCounter++; // This counter increments every time fire_triacs runs
}

void loop() { // Main Loop
if ( millis() >= ResetPeriod ) { // Measure the half period every PeriodResync milliseconds to prevent drift
measure_half_period();
}
FireTriac[0] = (DimRes * dim1) / 1024; // Read input and calc the next triac fire time
FireTriac[1] = (DimRes * dim2) / 1024; // Read input and calc the next triac fire time
FireTriac[2] = (DimRes * dim3) / 1024; // Read input and calc the next triac fire time
FireTriac[3] = (DimRes * dim4) / 1024; // Read input and calc the next triac fire time

//FireTriac[2] = (DimRes * analogRead(2)) / 1024; // Read input and calc the next triac fire time
//FireTriac[3] = (DimRes * analogRead(3)) / 1024; // Read input and calc the next triac fire time
}

void receiveEvent(int count)
{
if (count == I2C_MSG_IN_SIZE)
{
byte cmd = Wire.read();
byte port = Wire.read();
int value = Wire.read();
value += Wire.read()*256;
switch(cmd)
{
case CMD_DIGITAL_WRITE:
pinMode(port,OUTPUT);
digitalWrite(port,value);
break;
case CMD_DIGITAL_READ:
pinMode(port,INPUT_PULLUP);
clearSendBuffer();
sendBuffer[0] = digitalRead(port);
break;
case CMD_ANALOG_WRITE:
//analogWrite(port,value);
//triac=(port);
if (port == 4) triac1 = (port);
if (port == 5) triac2 = (port);
if (port == 6) triac3 = (port);
if (port == 7) triac4 = (port);
//if (port == 8) triac5 = (port);
//dim=(value);
//dim=dim / 8;
if (port == 4) dim1 = (value);
if (port == 5) dim2 = (value);
if (port == 6) dim3 = (value);
if (port == 7) dim4 = (value);
//if (port == 8) dim5 = (value);
break;
case CMD_ANALOG_READ:
clearSendBuffer();
if (port <= 4) valueRead = analogRead(port); // port <=4 to read analog value A0,A1,A2,A3 - A4 & A5 are I2C
if (port == 100) valueRead = ESPrms; // port is any number >4 up to 255
//if (port == 2) selector = analogRead(A2);
//if (port == 3) level = analogRead(A3);
sendBuffer[0] = valueRead & 0xff;
sendBuffer[1] = valueRead >> 8;
break;
}
}
}

void clearSendBuffer()
{
for(byte x=0; x < sizeof(sendBuffer); x++)
sendBuffer[x]=0;
}

void requestEvent()
{
Wire.write((const uint8_t*)sendBuffer,sizeof(sendBuffer));
}

I also is planning to use following rules in RPIEasy Rules tab and I tested it with pro mini with your original Promini plugin and it was storing dimmer values and triac value in integers at pro mini fine.

4 AC dimmers with 8 (128 x 8 = 1024 ) dimming level control menu for Raspberry pi using apds9960 gesture sensor with pro mini extender plugin on pi and slave code on pro mini

on 9960#Gesture do
if [9960#Gesture]=10
TaskValueSet,12,1,[dimmer#pin]+1
if [dimmer#pin]>9
TaskValueSet,12,1,9 # set higher limit of GPIO pin number for 4 dimmers
if [9960#Gesture]=20
TaskValueSet,12,1,[dimmer#pin]-1
if [dimmer#pin]<6
TaskValueSet,12,1,6 # set lower limit of GPIO pin number for 4 dimmers
if [9960#Gesture]=30
TaskValueSet,12,2,[dimmer#dimvalue]-128
if [dimmer#dimvalue]<0
TaskValueSet,12,2,0 # set lower limit for pwm value
if [9960#Gesture]=40
TaskValueSet,12,2,[dimmer#dimvalue]+128
if [dimmer#dimvalue]>1000
TaskValueSet,12,2,1000 # set upper limit for pwm value
if [9960#Gesture]=50
TaskValueSet,12,2,1000 # turn on dimmer at full power
if [9960#Gesture]=60
TaskValueSet,12,2,0 # turn off dimmer
endon

on dimmer#pin do
Publish %sysname%/dimmer/pin,[dimmer#pin]

endon

on dimmer#dimvalue do
Publish %sysname%/dimmer/dimvalue,[dimmer#dimvalue]
EXTPWM,[dimmer#pin],[dimmer#dimvalue] # Send PIN and PWM value to promini (stored pwm values in 4 different integers at promini for each Pin via I2C if used with PME (pro mini extender) plugin
oledcmd,clear
oledcmd,on
oled,6,1,Fan#[dimmer#pin]=[dimmer#dimvalue]

endon

Following are rules I use for esp8266 (espeasy) device for control using MPR121 sensor:

4 channel dimmer control

on key#press=17.00 do // MPR121 up key press for dimmer 1
TaskValueSet,12,1,[dummy#d1]+127 // Set dummy sensor 1 value
if [dummy#d1]>1000
TaskValueSet,12,1,1000
endif
EXTPWM,6,[dummy#d1] // set pro mini pin 6 pwm value to dummy sensor 1 value
oled,2,4,FAN1=[dummy#d1] // Set oled line 2 & letter 4 to dummy sensor 1 value
endon

on key#press=272.00 do // MPR121 down key press for dimmer 1
TaskValueSet,12,1,[dummy#d1]-128
if [dummy#d1]<0
TaskValueSet,12,1,0
endif
EXTPWM,6,[dummy#d1]
oled,2,4,FAN1=[dummy#d1]
endon

on key#press=34.00 do
TaskValueSet,12,2,[dummy#d2]+128
if [dummy#d2]>1000
TaskValueSet,12,2,1000
endif
EXTPWM,7,[dummy#d2]
oled,2,4,FAN2=[dummy#d2]
endon

on key#press=544.00 do
TaskValueSet,12,2,[dummy#d2]-128
if [dummy#d2]<0
TaskValueSet,12,2,0
endif
EXTPWM,7,[dummy#d2]
oled,2,4,FAN2=[dummy#d2]
endon

on key#press=68.00 do
TaskValueSet,12,3,[dummy#d3]+128
if [dummy#d3]>1000
TaskValueSet,12,3,1000
endif
EXTPWM,8,[dummy#d3]
oled,2,4,FAN3=[dummy#d3]
endon

on key#press=1088.00 do
TaskValueSet,12,3,[dummy#d3]-128
if [dummy#d3]<0
TaskValueSet,12,3,0
endif
EXTPWM,8,[dummy#d3]
oled,2,4,FAN3=[dummy#d3]
endon

on key#press=136.00 do
TaskValueSet,12,4,[dummy#d4]+128
if [dummy#d4]>1000
TaskValueSet,12,4,1000
endif
EXTPWM,9,[dummy#d4]
oled,2,4,FAN4=[dummy#d4]
endon

on key#press=2176.00 do
TaskValueSet,12,4,[dummy#d4]-128
if [dummy#d4]<0
TaskValueSet,12,4,0
endif
EXTPWM,9,[dummy#d4]
oled,2,4,FAN4=[dummy#d4]
endon

on dimmer1 do // when http://192.168.0.73/control?cmd=event,dimmer1=100 command issued from browser
TaskValueSet 12,1,%eventvalue% // store pwm level value of 0 to 1023 from above command into dummy sensor
oled,2,4,FAN1=[dummy#d1]
endon

on dimmer2 do
TaskValueSet 12,2,%eventvalue%
oled,2,4,FAN2=[dummy#d2]
endon

on dimmer3 do
TaskValueSet 12,3,%eventvalue%
oled,2,4,FAN3=[dummy#d3]
endon

on dimmer4 do
TaskValueSet 12,4,%eventvalue%
oled,2,4,FAN4=[dummy#d4]
endon

I hope this is not too confusing.

Thanks.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

It was a great challange to me, but now they compiles at least...
https://github.com/enesbcs/ESPEasySlaves/blob/master/MiniProExtenderAC/MiniProExtenderAC.ino
https://github.com/enesbcs/ESPEasySlaves/blob/master/MiniProExtenderACS/MiniProExtenderACS.ino

from rpieasy.

happytm avatar happytm commented on July 19, 2024

I tested your sketches but did not work for me so I created following sketch & used latest plugin which work perfect for me. I think finally you have resolved this issue . I watched serial console on pro mini and it is changing integer values properly. Also I was getting proper values in to rpieasy for 3 analog values from pro mini. I very much appreciate your effort. Also can you commit following sketch for future reference before I mess it up again.

/********************************************************************************************************************\

  • Arduino project "ESP Easy" Copyright www.esp8266.nu
  • This program is free software: you can redistribute it and/or modify it under the terms of the GNU
  • General Public License as published by the Free Software Foundation, either version 3 of the License,
  • or (at your option) any later version.
  • This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  • without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  • See the GNU General Public License for more details.
  • You received a copy of the GNU General Public License along with this program in file 'License.txt'.
  • IDE download : https://www.arduino.cc/en/Main/Software
  • ESP8266 Package : https://github.com/esp8266/Arduino
  • Source Code : https://sourceforge.net/projects/espeasy/
  • Support : http://www.esp8266.nu
  • Discussion : http://www.esp8266.nu/forum/
  • Additional information about licensing can be found at : http://www.gnu.org/licenses
    ******************************************************************************************************************/
    // This file is to be loaded onto an Arduino Pro Mini so it will act as a simple IO extender to the ESP module.
    // Communication between ESP and Arduino is using the I2C bus, so only two wires needed.
    // It is possible to run the Pro Mini on 3V3, although the 16MHz versions do not officially support this at 16MHzl
    // By working on 3.3volt you can skip levelconverters on I2C, but no guarantee that it will work stable.
    // Arduino Mini Pro uses A4 and A5 for I2C bus. ESP I2C can be configured but they are on GPIO-4 and GPIO-5 by default.

/*
AC Light Control

Updated by Robert Twomey [email protected]

Changed zero-crossing detection to look for RISING edge rather
than falling. (originally it was only chopping the negative half
of the AC wave form).

Also changed the dim_check() to turn on the Triac, leaving it on
until the zero_cross_detect() turn's it off.

Ryan McLaughlin [email protected]

The hardware consists of an Triac to act as an A/C switch and
an opto-isolator to give us a zero-crossing reference.
The software uses two interrupts to control dimming of the light.
The first is a hardware interrupt to detect the zero-cross of
the AC sine wave, the second is software based and always running
at 1/128 of the AC wave speed. After the zero-cross is detected
the function check to make sure the proper dimming level has been
reached and the light is turned on mid-wave, only providing
partial current and therefore dimming our AC load.

Thanks to http://www.andrewkilpatrick.org/blog/?page_id=445
and http://www.hoelscher-hi.de/hendrik/english/dimmer.htm

*/
#include <Wire.h>
#include <TimerOne.h> // Avaiable from http://www.arduino.cc/playground/Code/Timer1

#define I2C_MSG_IN_SIZE 4
#define I2C_MSG_OUT_SIZE 4

#define CMD_DIGITAL_WRITE 1
#define CMD_DIGITAL_READ 2
#define CMD_ANALOG_WRITE 3
#define CMD_ANALOG_READ 4
//#define CMD_ASK_MAX_FUNC 0x10

//volatile byte I2CReceived = 0;
//volatile byte I2CDataReady = 0;
volatile uint8_t sendBuffer[I2C_MSG_OUT_SIZE];
//uint8_t EmptBuffer[I2C_MSG_OUT_SIZE];

//volatile int value = 0;
//volatile byte port = 0;
//volatile byte cmd = 0;
int ESPrms=0; // value to be sent over I2C to ESP

int triac;
int dim;

volatile int i=0; // Variable to use as a counter
volatile boolean zero_cross=0; // Boolean to store a "switch" to tell us if we have crossed zero

int triac1; // Output to Opto Triac1
int triac2; // Output to Opto Triac2
int triac3; // Output to Opto Triac3
int triac4; // Output to Opto Triac4
int triac5; // Output to Opto Triac5
int triac6; // Output to Opto Triac6

int LED = 10; // LED for testing

int dim1; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim2; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim3; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim4; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim5; // Dimming level (0-128) 0 = on, 128 = 0ff
int dim6; // Dimming level (0-128) 0 = on, 128 = 0ff

int freqStep = 65; // or 78 based on power supply : This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want.
//
// The only tricky part is that the chopper circuit chops the AC wave twice per
// cycle, once on the positive half and once at the negative half. This meeans
// the chopping happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply.

// To calculate freqStep you divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps.
//
// (1000000 uS / 120 Hz) / 128 brightness steps = 65 uS / brightness step or (1000000 uS / 100 Hz) / 128 brightness steps = 78 uS / brightness step
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave or 100 Hz =

void setup()
{
// for (byte x = 0; x < sizeof(sendBuffer); x++)
// sendBuffer[x] = 0;
// for (byte x = 0; x < sizeof(EmptBuffer); x++)
// EmptBuffer[x] = 0xff;
Wire.begin(0x3f);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(9600);

pinMode(triac1, OUTPUT); // Set the Triac1 pin as output
pinMode(triac2, OUTPUT); // Set the Triac2 pin as output
pinMode(triac3, OUTPUT); // Set the Triac3 pin as output
pinMode(triac4, OUTPUT); // Set the Triac4 pin as output
pinMode(triac5, OUTPUT); // Set the Triac5 pin as output
pinMode(triac6, OUTPUT); // Set the Triac6 pin as output */

pinMode(LED, OUTPUT); // Set the LED pin as output

attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
Timer1.initialize(freqStep); // Initialize TimerOne library for the freq we need
Timer1.attachInterrupt(dim_check, freqStep);
// Use the TimerOne Library to attach an interrupt
// to the function we use to check to see if it is
// the right time to fire the triac. This function
// will now run every freqStep in microseconds.
}

/* ******************************************************************************************************************
This part in the loop found here: [url] https://forum.arduino.cc/index.php?topic=179541.0 [/url] tnx to dc42
constant 75.7576 depends on the sensitivity of the ACS712 module
Sensitivity Min<Typ<Max mV/A
for 30A: 64< 66< 68 mV/A > constant = 5/.066 = 75.76
for 10A: 96<100<104 mV/A > constant = 5/.1 = 50.00
for 5A: 180<185<190 mV/A > constant = 5/.185 = 27.03
*/

const int currentPin = A0; // ADC pin used for ACS712
const unsigned long sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 250L; // number of samples 400 microsecond each
const unsigned long sampleInterval = sampleTime/numSamples; // sampling interval, must be longer than then ADC conversion time
int adc_zero = 514; // relative zero of the ACS712 for me 514 was best. 511
int valueRead;

void zero_cross_detect() {
zero_cross = true; // set the boolean to true to tell our dimming function that a zero cross has occured
i=0;
// since the control pin stays high, the TRIAC won't 'unlatch'
// when zero-crossing, so I need to put the pins to LOW
digitalWrite(triac1, LOW);
digitalWrite(triac2, LOW);
digitalWrite(triac3, LOW);
digitalWrite(triac4, LOW);
digitalWrite(triac5, LOW);
digitalWrite(triac6, LOW);

// writing pins is like 10 times faster if
// we write the register directly
// instead of using 'digitalWrite'

}

// Turn on the TRIAC at the appropriate time
void dim_check() {
if(zero_cross == true) {

if(i>=dim1)  {                     
  digitalWrite(triac1, HIGH);  // turn on triac1
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   
                       
  if(i>=dim2) {                     
  digitalWrite(triac2, HIGH);  // turn on triac2 
  
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   
           
   
  if(i>=dim3) {                     
  digitalWrite(triac3, HIGH);  // turn on triac3
  
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   


 if(i>=dim4) {                     
  digitalWrite(triac4, HIGH);  // turn on triac4
  
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   

if(i>=dim5) {
digitalWrite(triac5, HIGH); // turn on triac5

  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}   

  if (i>=dim6) {                     
  digitalWrite(triac6, HIGH);  // turn on triac6
  i=0;  // reset time step counter                         
  zero_cross = false; //reset zero cross detection
}    

else {
  
  i++; // increment time step counter 

}
 
                  
}                                

}

// void handleI2C()

void loop()
{
if (triac == 4) {
dim1=dim;

      }
     if (triac == 5) {
        dim2=dim; 
      }

      if (triac == 6) {
        dim3=dim; 
      }
     if (triac == 7) {
        dim4=dim; 
      }

     if (triac == 8) {
        dim5=dim; 
      }

      if (triac == 9) {
        dim6=dim; 
      }

      dim_check();

//dim = dim / 8; // set dimmer value to global integer dim
//dim = analogRead(POT_pin) / 8; // read dimmer value from potentiometer
analogWrite(LED, dim); // write dimmer value to the LED, for debugging

Serial.print("dim = ");
Serial.print(dim);

//Serial.print("triac = ");
//Serial.print(triac);

Serial.print(" t1 = ");
Serial.print(triac1);
Serial.print(" d1 = ");
Serial.print(dim1);
Serial.print(" t2 = ");
Serial.print(triac2);
Serial.print(" d2 = ");
Serial.print(dim2);
Serial.print(" t3 = ");
Serial.print(triac3);
Serial.print(" d3 = ");
Serial.print(dim3);
Serial.print(" t4 = ");
Serial.print(triac4);
Serial.print(" d4 = ");
Serial.print(dim4);
Serial.print(" t5 = ");
Serial.print(triac5);
Serial.print(" d5 = ");
Serial.print(dim5);
Serial.print(" t6 = ");
Serial.print(triac6);
Serial.print(" d6 = ");
Serial.print(dim6);

// Serial.println(" ESPrms = ");
// Serial.print(ESPrms);

delay(10000);
Serial.print('\n');

}

void receiveEvent(int count)
{
if (count == I2C_MSG_IN_SIZE)
{
byte cmd = Wire.read();
byte port = Wire.read();
int value = Wire.read();
value += Wire.read()*256;
switch(cmd)
{
case CMD_DIGITAL_WRITE:
pinMode(port,OUTPUT);
digitalWrite(port,value);
break;
case CMD_DIGITAL_READ:
pinMode(port,INPUT_PULLUP);
clearSendBuffer();
sendBuffer[0] = digitalRead(port);
break;
case CMD_ANALOG_WRITE:
//analogWrite(port,value);
triac=(port);
dim=(value);
if (port == 4) triac1 = (port);
if (port == 5) triac2 = (port);
if (port == 6) triac3 = (port);
if (port == 7) triac4 = (port);
if (port == 8) triac5 = (port);
if (port == 9) triac6 = (port);
break;

    case CMD_ANALOG_READ:
    
    if (port <= 4) valueRead = analogRead(port); // port <=4 to read analog value A0,A1,A2,A3 - A4 & A5 are I2C
   // if (port > 79) valueRead = ESPrms; // port is any number >4 up to 255
    sendBuffer[0] = valueRead & 0xff;
    sendBuffer[1] = valueRead >> 8;
    
    break;
  }

}
}

void clearSendBuffer()
{
for(byte x=0; x < sizeof(sendBuffer); x++)
sendBuffer[x]=0;
}

void requestEvent()
{
Wire.write((const uint8_t*)sendBuffer,sizeof(sendBuffer));
}

Thank you.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

I can add it, but this sketch is using the same old I2C handling, which can lead a lockup because analogread() function located are in the receiveEvent block which is an ISR function. I am afraid that after several hour it will come about.

from rpieasy.

enesbcs avatar enesbcs commented on July 19, 2024

Uploaded to https://github.com/enesbcs/ESPEasySlaves/tree/master/MiniProExtenderOACS
In case of further bugs, please open a new issue.

from rpieasy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.