Open mcpat-it opened 10 months ago
Hi, I'm not familiar with smbus. However, you have to read at least 3 bytes from the I2C bus. The first 2 bytes are the rotary value, the third byte ist the switch state.
thx for the fast answer, I tried yesterday up to the time to go to bed ;)
I tried this code, which is working if I modify the firmware of the rotary encoder:
from smbus import SMBus
import time
addr = 0x36 # bus address
data_fetch = 0x00
bus = SMBus(1) # indicates /dev/ic2-1
oldvalue = 0
pressed = 0
#not working
#bus.write_i2c_block_data(addr, 0x0, [0x1, 0x20, 0x01, 0x00])
while True:
try:
z = bus.read_i2c_block_data(addr, 0x0, 3)
if z[0] != oldvalue or z[2] != pressed:
oldvalue = z[0]
pressed = z[2]
print("0: " + str(z[0]))
print("1: " + str(z[1]))
print("2: " + str(z[2]))
time.sleep(0.25)
except:
print('exiting...')
break
What I had to do, to get any values, is to prevent to write anything because the read_i2c_block_data
is writting a value first, and then it is reading. The value is the second parameter, in my case 0x0
.
So I inserted in your firmware:
Last line ENC_set(0, 9, 1, 5, I2C_REG[3]);
:
int main(void) {
// Local variables
int16_t rval, rmin, rmax, rstep; // for handling encoder parameters
// Setup
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 1); // set clock frequency to 10 MHz
I2C_init(); // setup I2C
ENC_init(); // setup rotary encoder
sei(); // enable interrupts
ENC_set(0, 9, 1, 5, I2C_REG[3]);
...
And I "disabled" the I2C_REG_changed
"function". Additional, and I don't know why, I had to add on a lower stage I2C_REG[0] = (uint8_t)(rval & 0xff);
and I2C_REG[1] = (uint8_t)(rval >> 8);
again... Without adding, I can only get the value of the switch which is your code line I2C_REG[2] = !pinRead(PIN_ENC_SW);
// Loop
while(1) {
// Update rotary encoder settings if I2C registers have changed
if(I2C_REG_changed && !I2C_busy) {
//cli(); // disable interrupts for atomic ops
//rval = ((uint16_t)I2C_REG[1] << 8) | (uint16_t)I2C_REG[0];
//rmin = ((uint16_t)I2C_REG[5] << 8) | (uint16_t)I2C_REG[4];
//rmax = ((uint16_t)I2C_REG[7] << 8) | (uint16_t)I2C_REG[6];
//rstep = ((uint16_t)I2C_REG[9] << 8) | (uint16_t)I2C_REG[8];
I2C_REG_changed = 0; // clear register changed flag
//sei(); // enable interrupts again
//ENC_set(rmin, rmax, rstep, rval, I2C_REG[3]); // set rotary encoder
}
// Update I2C registers if rotary encoder wheel value has changed
if(ENC_changed && !I2C_REG_changed && !I2C_busy) {
cli(); // disable interrupts for atomic ops
rval = ENC_count / 2; // get encoder counter value
I2C_REG[0] = (uint8_t)(rval & 0xff); // store low byte to register
I2C_REG[1] = (uint8_t)(rval >> 8); // store high byte to register
ENC_changed = 0; // clear encoder changed flag
sei(); // enable interrupts again
}
// Update rotary encoder switch register
I2C_REG[2] = !pinRead(PIN_ENC_SW);
I2C_REG[0] = (uint8_t)(rval & 0xff); // store low byte to register
I2C_REG[1] = (uint8_t)(rval >> 8); // store high byte to register
}
So my main questions are
ENC_set
with Python?0x00
is deleting the ENC_set
values, which happens if I don't comment out the lines in the beginning of your codeI2C_RotaryEncoder_Test.ino
you are also loop.Sorry for this questions, I can code in c and other languages, but Pyhton is not my power language and I2C is my first try. So the firmware has a lot of lines like cli()
, sei()
and ISR
which I didn't see before.
Thank you again for your help! Btw, I am from Austria and your name sounds german ;)
Regards Patrick
I can't understand your changes at the moment. Have you also changed anything in the interrupt service routines? (sei(), cli() and ISR belong to interrupts, which are triggered whenever the rotary encoder is messed with or I2C communication is running). It's also not entirely clear to me when you're talking about the source code for the ATtiny (it's written in C) and when you're talking about the software on the other side of the I2C connection (in your case, it's probably Python on the Raspberry Pi).
Hi,
I tried to get the value with python on raspberry pi via smbus, but I don't know how to get the rotary enoder switch state, could you please help? Here my code for now which is reading the value of the wheel:
And second question, is there a better way to get the actual value without a while loop?
Thank you in advance, Patrick