ProMiniExtender

Moderators: grovkillen, Stuntteam, TD-er

Post Reply
Message
Author
User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

ProMiniExtender

#1 Post by costo » 10 Jan 2016, 01:31

I've been playing with this ProMiniExtender a little and i like it.
Indeed R62 now gives analog values upto 1023 while R60 had 255 as maximum analog value.

I tested with a Arduino nano. A4 & A5 on the Arduino are I2C. The wire library takes care that these pins never will be set OUTPUT_HIGH, only OUTPUT_LOW or INPUT are possible. So it is no problem to connect I2C pins from a 5 volt Arduino to 3.3V ESPEasy hardware as long as you connect your I2C pullup resistors to 3.3 volt.
I tried to let the Nano run on 3.3Volt and it works, probably not as reliable as on 5V but that's OK for me. To make it easy to see if the arduino is running I put a BlinkWithoutDelay program into the loop to let the builtin LED on pin 13 blink.
This configuration of ESPEasy with a PME opens many new exiting possiblities for local intelligence.
As the response inside the PME is direct while values send over I2C from/to ESPEasy or a server are only updated once/minute.
For instance a thermostate for a heating device or a intelligent doorbell can be programmed within the PME's loop if care is taken to avoid/minimize delay() and SerialPrint() commands.

While studying the MiniProExtender source I read:
#define CMD_DIGITAL_WRITE 1
#define CMD_DIGITAL_READ 2
#define CMD_ANALOG_WRITE 3
#define CMD_ANALOG_READ 4

But ESPEasy only let me READ values. Are the WRITE commands for future releases?
It would be cool to send some values from Domoticz to the PME and program something in the PME that can use this values. I can think of many usefull things to do inside the PME.

Also it would be great to see a formula line for the analog value so you can scale it down to a value that is better interpretable by humans or Domoticz.
If I connect a analog pin to Vc it reads 1023 and I like to see 3.30 there, so the formula line should be like: %value%*0.003226.

Could this Formula field be implemented in a future release ?

Martinus

Re: ProMiniExtender

#2 Post by Martinus » 10 Jan 2016, 14:20

With R63 on github, you can now use the formula field. Tested and my LCD now shows 3.30 volts reading vcc...

You can write to the PME outputs with generic http requests, just like the build-in GPIO:

Code: Select all

http://<ESP IP address>/control?cmd=EXTGPIO,<pin>,<state>
http://<ESP IP address>/control?cmd=EXTPWM,<pin>,<value>

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#3 Post by costo » 10 Jan 2016, 23:34

Martinus wrote:With R63 on github, you can now use the formula field. Tested and my LCD now shows 3.30 volts reading vcc...

You can write to the PME outputs with generic http requests, just like the build-in GPIO:

Code: Select all

http://<ESP IP address>/control?cmd=EXTGPIO,<pin>,<state>
http://<ESP IP address>/control?cmd=EXTPWM,<pin>,<value>
Thanks for showing me how to use it.
It will be easy to catch these values and store them into global variables that can be used inside the loop.

mkotek
Normal user
Posts: 116
Joined: 15 Dec 2015, 10:58
Location: Lomianki, Poland
Contact:

Re: ProMiniExtender

#4 Post by mkotek » 12 Jan 2016, 17:54

Does it all mean, I can connect my Arduino Pro Mini to ESP and use GPIOs from Arduino as extensions of GPIOs on ESP?
Would I be able to run my own sketch on Arduino if I enhance the ino for Arduino that is provided?
Michal 'Kotek', greetings from Poland. Zapraszam na mój blog o automatyce domowej po polsku: http://www.ukotka.com.

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#5 Post by costo » 12 Jan 2016, 19:59

mkotek wrote:Does it all mean, I can connect my Arduino Pro Mini to ESP and use GPIOs from Arduino as extensions of GPIOs on ESP?
Would I be able to run my own sketch on Arduino if I enhance the ino for Arduino that is provided?
Exactly.

If you look inside the MiniProExtender sketch you see a setup and a empty loop.
In the setup you see: Wire.onReceive(receiveEvent); and Wire.onRequest(requestEvent);
which are handlers, like interrupt handlers but these handlers respond to I2C events.

So the MiniProExtender sketch goes maybe a million times/second through the empty loop waiting for a I2C event.
Your own sketch can be put into the empty loop.
As a very simple example, I added one declaration line, one line in setup() and a sketch in the loop, what I added looks like this:

unsigned long oldMillis = 0;

void setup()
{
Wire.begin(0x7f); // already there
Wire.onReceive(receiveEvent); // already there
Wire.onRequest(requestEvent); // already there
pinMode(13, OUTPUT);
}

void loop() {
if (millis() - oldMillis >= 1000) {
oldMillis = millis();
if (digitalRead(13) == LOW) { digitalWrite(13, HIGH);}
else { digitalWrite(13, LOW); }
}
}
This simple program gives the PME a sort of heartbeat, for a second led on, then a second led off , and so on.
You can also put a more complicated program inside the loop but I think you must take care not blocking the PME with code like delay() or SerialPrint().

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#6 Post by tozett » 23 Jan 2016, 21:42

somebody experimented similar, but tried to push json messages over i2c and found a 30kb limit.
maybe of interest for the pro-mini development?

https://www.ibm.com/developerworks/comm ... on?lang=en

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#7 Post by tozett » 19 Feb 2016, 08:49

the pro-mini-extender proMiniExtender could be reversed,
so the ESP is somehow backpacked to the arduino,
still both together building a sensor-node (on batteries?)

like this, already:
https://www.openhardware.io/view/5/Batt ... sor-no-SMD

Martinus

Re: ProMiniExtender

#8 Post by Martinus » 19 Feb 2016, 14:31

tozett wrote:the pro-mini-extender proMiniExtender could be reversed,
so the ESP is somehow backpacked to the arduino,
still both together building a sensor-node (on batteries?)

like this, already:
https://www.openhardware.io/view/5/Batt ... sor-no-SMD
Your pointing towards a different solution. This is an Atmel 328 with a NRF24L01 radio.
Runs perfect on batteries as the NRF only requires 10 mA when active and it usually only sends very short (<32 bytes) data packages.
This needs a separate MCU because the NRF24L01 can't run Arduino sketches. The NRF is also not a Wifi radio.

When using an ESP, it doesn't make much sense to have another MCU in the solution unless you need more IO (or maybe some task that the ESP cannot do due to timing constrains caused by necessary Wifi handling)

And that's why we have the ProMini extender.

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#9 Post by tozett » 19 Feb 2016, 18:24

Martinus wrote: This is an Atmel 328 with a NRF24L01 radio.
sorry, sorry,
i was only quickly looking at the picture a mis-recognized this as an ESP modul :?

as my pure ESP (no pcb-boards, they are still in chinese-mail..) dont have long runtimes (days, not months) and they dont respond after a while,
so i was looking for a remote-way to cold-restart them. that helps with all, and that would be fine, works for me.

in my knx-homeautomation i can rely on (most) all components to run years without intervention.
my (still pure) esp´s run fine as nodes, but they need a helping hand after a time (in there hidden place).
i searched for a simple way for a remote cold-restart with this PCB solution. hmmm

the idea of pete scargill was stunning, where he sends his nodes from a central HUB (node-red, domoticz) a heartbeat to the nodes, and coded them, that they cold-restart (pin 16-to-reset) if the heartbeat misses for sometime. could be a function from node-to-node, or in the esp-node section..

but maybe only me hast this espEasy prob... :oops:

Martinus

Re: ProMiniExtender

#10 Post by Martinus » 20 Feb 2016, 12:01

tozett wrote:the idea of pete scargill was stunning, where he sends his nodes from a central HUB (node-red, domoticz) a heartbeat to the nodes, and coded them, that they cold-restart (pin 16-to-reset) if the heartbeat misses for sometime. could be a function from node-to-node, or in the esp-node section..
This is an idea, but if the ESP really hangs, who will pull the reset pin then? Am I missing something?

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#11 Post by tozett » 20 Feb 2016, 15:38

i think peter is somehow coding with the sdk,
as i have no idea of coding, i thought maybe he has a somehow separate and basic task,
as emergency task with a special priority in the ESP for this. (?)

but for the situation that the module really hangs, i guess one has to have a hardware watchdog.
something which holds VCC up, as long as the heartbeat comes in/or and goes out to certain hearbeat GPIO,
which holds this VCC/GND connection.

but as i am also no hardware engineer i only guess that is too complicated :shock: , but
i have no more clue than that this principal function would help with issues for modules
hidden at typical homeautomation places. behind walls, switches, ceilings ... :ugeek:

polluz
New user
Posts: 2
Joined: 22 Feb 2016, 12:17

Re: ProMiniExtender

#12 Post by polluz » 22 Feb 2016, 12:32

Hi,

I'm really new to this project and I find it very interestring.

I was trying the promini extender functionality and it works very well.

But I don't know how to (for example) read values of a dallas temperature sensor connected to a arduino gpio.

Is it possible?

Thanks and nice work to all the developers of this project!!!!

I hope It will grow.


(sorry for bad English)

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#13 Post by costo » 22 Feb 2016, 15:53

@ polluz, yes it is possible.

ESPEasy can read Int values from digital and analog ports on the ProMini
By changing the MiniProExtender sourceCode a little you can transfer all kind of integer values over the I2C bus.
You have to know a bit of programming Arduino in C to do this yourself.
I can only point you in the direction to do this, I will not give you a working solution.

For compiling the new Pro-Mini code you need to install the dallas library, read and prepare your temperature_value so that it is a (positive) integer number. Probably something like (temperature_value * 10 + 1000)
Store this value in a int variable , let's call this variable prepared_temperature. This must be coded inside the empty loop.

In the existing sketch you change a line like this:

Code: Select all

        case CMD_ANALOG_READ:
          clearSendBuffer();
          //change this line:[  int valueRead = analogRead(port); ] into:
          int valueRead = prepared_temperature;
          sendBuffer[0] = valueRead & 0xff;
          sendBuffer[1] = valueRead >> 8;
          break;
This would give you in ESPEasy the prepared value, you have to add a formula in 'Optional Setting' of espeasy which does the opposite, like this: %value%/10-100.

So you have to know a little bit of programming the Arduino yourself.
Ofcourse you can make some conditional tests inside the void receiveEvent(int count) of MiniProExtender so that it is still possible to read the analog pins and to read more temperature or other sensors where the variable 'port' points to a specific sensor.

I have not tested this (yet) but I expect it can work.
Succes with coding and please if you have a working piece of code share it with the community.

polluz
New user
Posts: 2
Joined: 22 Feb 2016, 12:17

Re: ProMiniExtender

#14 Post by polluz » 23 Feb 2016, 12:30

Thank You!

This could be a possible solution, but not really "EASY" as espeasy is.

What I was looking is the possibility to choose an arduino promini gpio and then apply espeasy function on it.

For example i choose gpio3 of promini and on this I select the apllication (thermometer or other things)

This will be a killer application because you could use easyness of espeasy with all gpio of an arduino!

I'm not an expert but maybe this feature is impossible to enable due to device limitations.

Anyway really thanks for help!

- polluz -

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#15 Post by tozett » 27 Apr 2016, 20:30

Hi,
i come back to some ideas, running simple code on the pro-mini-extender (PME) and found it newly sorted under slaves in the github.
https://github.com/ESP8266nu/ESPEasySlaves
so the ProMiniExtender is still alive, but the .ino is really barebone...
to get me running fast(er) with some experiments, would anybody be so kind to show up some working examples of code for the pro-mini-ext.?
:shock:
i would really be grateful for that, tanks..

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#16 Post by costo » 30 Apr 2016, 16:12

Code: Select all

/********************************************************************************************************************\
 * 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 = 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);
          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));
}

In the sketch for adc_zero = 514 was for my case the best value. Theoretically it should be 511. You should experiment with this value to get the lowest reading without current. It will never be zero because the ACS712 has some noise from itself. About 0.12 Ampere was the lowest zero reading I got.

In the device on ESPEasy:
Device: ProMini Extender
Name: Ampere
IDX: some value needed here, ID number from the server
Port: 100 (port number choosen in the sketch to couple with rms_value)
Port Type: Analog

Formula Value: %value%/1000 (to convert milliAmp to Ampere

Image

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#17 Post by costo » 30 Apr 2016, 17:06

double post
Last edited by costo on 30 Apr 2016, 17:12, edited 2 times in total.

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#18 Post by costo » 30 Apr 2016, 17:07

double post

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#19 Post by tozett » 14 Jul 2016, 08:19

hi,
i experimented with my fingerprint-reader http://www.esp8266.nu/forum/viewtopic.php?f=5&t=1617 and had the idea to use the pro-mini-extender as a sort of "level" shifter for 3.3V-5V conversion.
that arised my question:

do i need a level-shifter the 5V pro-mini (or 5V nano) --> to from ESP8266 (3.3V) (or is it vice-versa?) for the i2c-lines ?

anybody some experience with this?

i read here: http://playground.arduino.cc/Main/I2CBi ... velShifter
that it could work between two arduinos of 3.3V and 5V without a level-shifter for the i2c-lines, because the voltage level will not go beyond 3.3V for high.
Outside specs, (usually) works anyway

Connecting the 5V Arduino directly to a single 3.3V-powered I2C chip usually works, even though it violates official specifications in multiple ways.
5V I2C components can be connected to the SDA and SCL lines of the 3.3V I2C-bus. A high level will be 3.3V and not 5V, but in most cases it's enough to make it work.
anybody knows better? thanks for any information ...

Martinus

Re: ProMiniExtender

#20 Post by Martinus » 14 Jul 2016, 09:24

As far as i know, the Arduino I2C library for AVR sets internal pullups on I2C bus when I2C is enabled.
These are weak pullups to VCC, so if your Nano runs on 5V, the I2C lines will also carry 5V.

So officially, to stay within specs, you would need a level shifter.
Or you could patch the AVR I2C lib to disable the pullup resistors and use external pullup resistors connected to 3V3.

Or you could use a 3V3 Nano (I run my Pro Mini's on 3V3...)
Or try strong external pullups to 3V3 as they might cancel out the weak pullups effect. Just try and check with a multimeter.

tozett
Normal user
Posts: 734
Joined: 22 Dec 2015, 15:46
Location: Germany

Re: ProMiniExtender

#21 Post by tozett » 14 Jul 2016, 09:48

thanks a lot for fast and this much information,
i will go that way with strong pullups and multimeter checking... think you pointed me in the right directions.

by the way: wonderful ESPeasy! keep on counting firmware upwards .. ;-)
thanks a lot, ozett

happytm
Normal user
Posts: 107
Joined: 15 Aug 2016, 17:53

Re: ProMiniExtender

#22 Post by happytm » 15 Aug 2016, 18:12

Hi Costo,

I have followed your experiments with Pro-Mini Extender.I set up PME with your heartbeat code.It is working fine standalone and flashing led at pin 13.On esp8266 i have set up gpio-4 & gpio-5 as SDA and SCL respectively. I then connected pin D1 and D2 on esp8266 to pin A4 & A5 of PME running at 3.3V.Then I ran I2C scanner but it show following error messages :


MainConfigHardwareDevicesRulesTools

No I2C devices found
I2C Addresses in use Known devices
Unknown error at address 0x1
Unknown error at address 0x2
Unknown error at address 0x3
Unknown error at address 0x4
Unknown error at address 0x5
Unknown error at address 0x6
Unknown error at address 0x7
Unknown error at address 0x8

and it goes on until last address of 0x7f.

I also tried to set PME digital pins on/off.It shows json messages correctly but PME do not respond with my commands.

what am I missing here ? Please help me resolve this issue.

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#23 Post by costo » 17 Aug 2016, 16:52

@ happytm

First make the PME work without any modifications.
This mean you put the PME sketch into a Arduino module like Pro-Mini/Mini/Nano or whichever as long as it uses A4&A5 as I2C pins.

After connecting the Arduino you check the I2C, if it does not work you may need to change A4 and A5. Also make sure there are pull_up resistors of 3k3 or 4k7 between SDA/SCL and +3.3V.

happytm
Normal user
Posts: 107
Joined: 15 Aug 2016, 17:53

Re: ProMiniExtender

#24 Post by happytm » 17 Aug 2016, 18:40

Hi Costo,

I connected esp8266 and pro-mini directly without resistors.I thought pro-mini with 3.3v 8mhz did not need any resistors.Can you please tell me where i put resistors please ?

Thak you very much for your help.

happytm
Normal user
Posts: 107
Joined: 15 Aug 2016, 17:53

Re: ProMiniExtender

#25 Post by happytm » 18 Aug 2016, 00:12

Hi Costo,

I got my Pro-mini Working with Esp8266. I am planning to use Mini-Pro as AC Dimmer controller.I am new to espeasy and I want to add following code I found online to ProMini. Is it Possible to run this code with delays in the loop.You said delays could be problem in this sketch.If it is possible how can I incorporate this code in existing code? Please help me :

Code: Select all

/*
 AC Light Control
 
 Ryan McLaughlin <ryanjmclaughlin@gmail.com>
 
 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 <mark@chesterfamily.org>
 
 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 <TimerOne.h>                                  // http://www.arduino.cc/playground/Code/Timer1

// 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

void setup() {                                         // Begin setup
 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(TriacPin[0], OUTPUT);                        // Set the Triac pin as output
 pinMode(TriacPin[1], OUTPUT);                        // Set the Triac pin as output
 pinMode(TriacPin[2], OUTPUT);                        // Set the Triac pin as output
 pinMode(TriacPin[3], 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(TriacPin[0], HIGH);                   // Fire the Triac mid-phase
   delayMicroseconds(2);
   digitalWrite(TriacPin[0], 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(TriacPin[1], HIGH);                   // Fire the Triac mid-phase
   delayMicroseconds(2);
   digitalWrite(TriacPin[1], 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(TriacPin[2], HIGH);                   // Fire the Triac mid-phase
   delayMicroseconds(2);
   digitalWrite(TriacPin[2], 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(TriacPin[3], HIGH);                   // Fire the Triac mid-phase
   delayMicroseconds(2);
   digitalWrite(TriacPin[3], 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 * analogRead(0)) / 1024;    // Read input and calc the next triac fire time
   FireTriac[1] = (DimRes * analogRead(1)) / 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
}

User avatar
costo
Normal user
Posts: 500
Joined: 21 Nov 2015, 15:03
Location: NL, zw-NB

Re: ProMiniExtender

#26 Post by costo » 18 Aug 2016, 10:02

Delays of a few microseconds should not be a problem, delays of many milliseconds are expected to give problems.

I do not have the time to investigate this software and library TimerOne.h, You should try it yourself.

You have to change the analogRead() part in the loop into a integer(s) that is/are declared before the setup(), this integer(s) is/are the value(s) that can be sent as a command to ESPEasy and over I2C to the PME
.
I suggest you try this first with only one triac, commenting the parts for the other triacs out, to make the program simple.

happytm
Normal user
Posts: 107
Joined: 15 Aug 2016, 17:53

Re: ProMiniExtender

#27 Post by happytm » 19 Aug 2016, 02:54

Costo,

Thank you for you help.I will try to save values from extpwm command to pro mini to ints and try to fire the triacs based on those values.

Alan_37
Normal user
Posts: 18
Joined: 30 Apr 2017, 00:04

Re: ProMiniExtender

#28 Post by Alan_37 » 01 Mar 2019, 23:45

HI
I just connected the mini pro to espeasy I can control the pins 1 and 0
but I can't output any PWM from them is there any other Arduino Sketch somewhere ?
EXTPWM command dose not work for me

i am using this one below any idea why is that ??

#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];

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

void loop() {}

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();
int valueRead = analogRead(port);
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));
}

Post Reply

Who is online

Users browsing this forum: No registered users and 22 guests