How to wire I2C address pins (A0, A1, A2, …)?

When you want to use an I2C device like an EEPROM you might ask yourself how to wire the address pins (A0, A1 and A2).

The prime rule: No unconnected address pins

You need to remember the prime rule of I2C addressing: Never leave address pins unconnected unless explicitly allowed in the datasheet!

While there are some devices like the MCP3472 that allow floating address pins, most devices might not work properly (especially in noisy environments).

The second rule: Avoid address conflicts

You need to avoid having two parts with the same I2C address on the same I2C bus (address collisions)!
The I2C address of an I2C is 7 bits long and typically consists of a part-specific prefix (e.g. 0101) plus address pins (e.g. 0101ABC where A, B and C are the values of the address pins A0, A1 and A2)

First you need to find out whether there are other devices on the same I2C bus, i.e. other ICs that are connected to the same pair of SDA and SCL pins.

  • In case there are no other devices on the same I2C bus, you can wire all the pins to GND (you can also wire any of them to VCC in case that works better for you. If in doubt, wire them to GND!)
  • In case there are other devices on the same I2C bus, you need to proceed as outlined below

How to wire I2C address pins with multiple devices on the same I2C bus?

Multiple ICs with the same part number

If you have multiple ICs with the same part number on the I2C bus (examples: Multiple I2C ADCs, multiple I2C port expanders) it is quite easy to wire them to avoid address collisions: Just wire every one of the ICs differently. This will result in different addresses for each different IC.

Multiple different ICs

As we wrote before, you need to avoid having multiple ICs with the same address.

Most likely, different ICs will have different addresses in the first place, no matter how you wire their pins. However, this is not guaranteed! (if you are feeling lucky, producing only a small batch of prototype boards and don’t mind soldering around, you might as well test your luck and just assume they are different!).

Proceed as follows:

  • Open the datasheets of all the parts you want to use in your design
  • In each datasheet, find the section that lists the address details.

The address details will look like this:

In almost all I2C devices, the first few bits are fixed! The other bits (A_2, A_1 and A_0 in this example) depend on the address pins in one way or another.
While in most devices they represent the address pins directly, some devices try to have more configurable address slots than address pins and hence use floating address pins.

Compare these fixed bits between the devices. In case you can be sure that no two devices can have the same address, you can wire the address pins either to GND or to VCC since it doesn’t matter.

In this example, there obviously can’t be conflicting addresses since some of the fixed bits are different (as indicated by the red lines).

If you can’t be sure that there is no conflict, you need to assign the address pins appropriately so the parts have different I2C addresses.

Our recommendation is to actually write down the I2C addresses and check if they are actually different. This approach avoids hard-to-debug errors. You can do this using old-school pen & paper or do it in any editor.

Note: You should always write down the I2C address of each IC on the schematic, especially if you have multiple I2C parts! Not doing this typically results in having to re-do the calulation over and over again.

Interested on how we made the address diagrams in this post? Check out How to visualize I2C first byte structure in TikZ

Posted by Uli Köhler in Electronics

How to get milliseconds from pandas.Timedelta object

If you have a pandas.Timedelta object, you can use Timedelta.total_seconds() to get the seconds as a floating-point number with millisecond resolution and then multiply with one billion (1e3, the number of milliseconds in one second) to obtain the number of milliseconds in the Timedelta:

timedelta.total_seconds() * 1e3

In case you want an integer, use

int(round(timedelta.total_seconds() * 1e3))

Note that using round() is required here to avoid errors due to floating point precision.

or use this function definition:

def milliseconds_from_timedelta(timedelta):
    """Compute the milliseconds in a timedelta as floating-point number"""
    return timedelta.total_seconds() * 1e3

def milliseconds_from_timedelta_integer(timedelta):
    """Compute the milliseconds in a timedelta as integer number"""
    return int(round(timedelta.total_seconds() * 1e3))

# Usage example:
ms = milliseconds_from_timedelta(timedelta)
print(ms) # Prints 2000.752
ms = milliseconds_from_timedelta_integer(timedelta)
print(ms) # Prints 2001

 

Posted by Uli Köhler in pandas, Python

How to get microseconds from pandas.Timedelta object

If you have a pandas.Timedelta object, you can use Timedelta.total_seconds() to get the seconds as a floating-point number with microsecond resolution and then multiply with one million (1e6, the number of microseconds in one second) to obtain the number of microseconds in the Timedelta:

timedelta.total_seconds() * 1e6

In case you want an integer, use

int(round(timedelta.total_seconds() * 1e6))

Note that using round() is required here to avoid errors due to floating point precision.

or use this function definition:

def microseconds_from_timedelta(timedelta):
    """Compute the microseconds in a timedelta as floating-point number"""
    return timedelta.total_seconds() * 1e6

def microseconds_from_timedelta_integer(timedelta):
    """Compute the microseconds in a timedelta as integer number"""
    return int(round(timedelta.total_seconds() * 1e6))

# Usage example:
us = microseconds_from_timedelta(timedelta)
print(us) # Prints 2000751.9999999998

us = microseconds_from_timedelta_integer(timedelta)
print(us) # Prints 2000752
Posted by Uli Köhler in pandas, Python

How to get nanoseconds from pandas.Timedelta object

If you have a pandas.Timedelta object, you can use Timedelta.total_seconds() to get the seconds as a floating-point number with nanosecond resolution and then multiply with one billion (1e9, the number of nanoseconds in one second) to obtain the number of nanoseconds in the Timedelta:

timedelta.total_seconds() * 1e9

In case you want an integer, use

int(round(timedelta.total_seconds() * 1e9))

Note that using round() is required here to avoid errors due to floating point precision.

or use this function definition:

def nanoseconds_from_timedelta(timedelta):
    """Compute the nanoseconds in a timedelta as floating-point number"""
    return timedelta.total_seconds() * 1e9

def nanoseconds_from_timedelta_integer(timedelta):
    """Compute the nanoseconds in a timedelta as integer number"""
    return int(round(timedelta.total_seconds() * 1e9))

# Usage example:
ns = nanoseconds_from_timedelta(timedelta)
print(ns) # Prints 2000751999.9999998

ns = nanoseconds_from_timedelta_integer(timedelta)
print(ns) # Prints 2000752000

 

Posted by Uli Köhler in pandas, Python

How to create pandas.Timedelta object from two timestamps

If you have two pandas.Timestamp objects, you can simply substract them using the minus operator (-) in order to obtain a pandas.Timedelta object:

import pandas as pd
import time

# Create two timestamps
ts1 = pd.Timestamp.now()
time.sleep(2)
ts2 = pd.Timestamp.now()

# The difference of these timestamps is a pandas.Timedelta object.
timedelta = ts2 - ts1
print(timedelta) # Prints '0 days 00:00:02.000752'

 

Posted by Uli Köhler in pandas, Python

How to get current timestamp in Pandas

Use

import pandas as pd

current_timestamp = pd.Timestamp.now()

pd.Timestamp.now() will return the timestamp as pandas.Timestamp object.

Example:

>>> import pandas as pd
>>> pd.Timestamp.now()
Timestamp('2019-10-27 16:11:43.998993')
Posted by Uli Köhler in pandas, Python

How to fix ModuleNotFoundError: No module named ‘dateutil’

Problem:

You want to use the dateutil library in Python, but when you try to import it, you see an exception like this:

Traceback (most recent call last):
  File "my.py", line 11, in <module>
    import dateutil as dl
ModuleNotFoundError: No module named 'dateutil'

When you try installing it using e.g. pip install dateutil you see this error message:

Collecting dateutil
  Could not find a version that satisfies the requirement dateutil (from versions: )
No matching distribution found for dateutil

Solution:

The package is named python-dateutil. Install using

sudo pip install python-dateutil

or (for Python3)

sudo pip3 install python-dateutil

 

Posted by Uli Köhler in Python

Voltage divider output voltage calculator (from R1 & R2)

TechOverflow calculators:
You can enter values with SI suffixes like 12.2m (equivalent to 0.012) or 14k (14000) or 32u (0.000032).
The results are calculated while you type and shown directly below the calculator, so there is no need to press return or click on a Calculate button. Just make sure that all inputs are green by entering valid values.

Input voltage:

V

Top resistor:

Ω

Bottom resistor:

Ω

V_{out} = V_{in} \cdot \frac{R_2}{R_1\cdot R_2}
Posted by Uli Köhler in Calculators, Electronics

What is the pullup/pulldown resistor value on the SAMD21?

Also see Does the SAMD21 have pullups on every pin?

The ATSAMD21 microcontrollers have integrated pull-up and pull-down resistors which you can enable or disable in software.

The nominal value of the pull-up and pull-down resistors is 40 kΩ but it can be between 20 kΩ and 60 kΩ.

Refer to the datasheet, section 37.9.1 for more details.

Posted by Uli Köhler in Allgemein

Does the SAMD21 have pullups on every pin?

Yes, the ATSAMD21 family of microcontrollers has internal pull-ups (and pull-downs) on every Port A / Port B pin (like PB03 or PA14) except PA24 and PA25. You can enable or disable the pullups in software.

The RESET pin also has an internal pull-up which is always active and can’t be disabled.

Posted by Uli Köhler in Electronics

Which pins can be used as external interrupts on the SAMD21?

The SAMD21 family of microcontrollers features the EIC (External Interrupt Controller) module which you can use to have up to 16 external interrupts on rising, falling or both edges.

External interrupts are only possible on the EXTINT0 to EXTINT15 pins (each of the EXTINTs is called an external interrupt line, e.g. EXTINT0 is called external interrupt line 0).

Continue reading →

Posted by Uli Köhler in Electronics

Where to find the SAMD20 microcontroller reference manual?

There is no such reference manual. All the information is included in the SAMD20 datasheet.

While you might be more familiar with microcontrollers such as the STM32 where there is a datasheet for each sub-family and a separate reference manual, Microchip/Atmel has chosen to include all the information in the datasheet.

Posted by Uli Köhler in Electronics

Where to find the SAMD21 microcontroller reference manual?

There is no such reference manual. All the information is included in the SAMD21 datasheet.

While you might be more familiar with microcontrollers such as the STM32 where there is a datasheet for each sub-family and a separate reference manual, Microchip/Atmel has chosen to include all the information in the datasheet.

Posted by Uli Köhler in Electronics

How to connect the WP (Write Protect) pin of an EEPROM?

Usually, you should connect the WP pin to GND. This disables write protection, i.e. you can read and write to the EEPROM.

The WP pin is active-high, i.e. pulling it to VCC enables the write protection. For details, refer to your EEPROM’s datasheet, e.g. the AT24CS04 dataheet. The function of the write protect pin is idential in all 24xx series EEPROMs, even across manufacturers.

In case you want to enable write protection to avoid accidentally overwriting your data, you should connect the WP pin to a microcontroller or an external logic circuitry. Connecting it to a microcontroller is typically the easiest option.

The following picture shows an EEPROM connected correctly in KiCAD so that read and write is enabled.

Posted by Uli Köhler in Electronics

How to check NODE_ENV environment variable in Node.JS

You can use process.env.NODE_ENV to check the value of the NODE_ENV environment variable in Node.JS:

if(process.env.NODE_ENV == "development") {
    // TODO your code goes here
}

or

if(process.env.NODE_ENV == "production") {
    // TODO your code goes here
}

Note that by default NODE_ENV is undefined so remember to handle that case appropriately.

Posted by Uli Köhler in Javascript, NodeJS

Minimal Koa.JS example with Router & Body parser

This is the minimal Koa.JS application which I use as a template for new NodeJS webserver applications.

#!/usr/bin/env node
const router = require('koa-router')();
const koaBody = require('koa-body');
const Koa = require('koa');
const app = new Koa();

app.use(koaBody());

router.get('/', async ctx => {
    ctx.body = "Hello world";
});

app.use(router.routes());

if (!module.parent) app.listen(3000);

Install the requirements using

npm i --save koa koa-router koa-body

and run using

node index.js

assuming you have saved our code from above in index.js.

Now (with the node index.js command still running) go to http://localhost:3000 . You should see Hello world there. Now it’s your turn to continue on your endeavour to develop the world’s greatest webservers 🙂

Posted by Uli Köhler in Javascript, NodeJS

What does ‘if (!module.parent)’ mean in NodeJS?

In NodeJS applications you often see code like

if (!module.parent) {
    app.listen(3000);
}

This means: Run app.listen(3000) only if you are running the file

Suppose this code is in index.js. In this case, the code will only be executed if you run index.js directly (i.e. using node index.js) and not if index.js is required from another file (by require('./index.js');).

If index.js is required from another Javascript module (i.e. file), module.parent will be set to that module.

Posted by Uli Köhler in Javascript, NodeJS

How to fix ‘docker: invalid reference format.’

Problem:

You want to start docker container but you see an error message like this:

docker: invalid reference format.

Solution:

Docker is telling you that the syntax of the docker image name (& version) is wrong. Note that this is not the same as docker not being able to find the image in the registry. Docker will not even be able to lookup the image in the registry if you see an invalid reference format error!

Common causes include:

  • You used a colon at the end of the image name, e.g. ubuntu: – omit the colon ; using just ubuntu will refer to ubuntu:latest
  • You used a dash at the end of the image name, e.g. ubuntu- – omit the dash ; using just ubuntu will refer to ubuntu:latest
  • You used variables like ubuntu:$VERSION but $VERSION is not set. Ensure you have set $VERSION to an appropriate (non-empty) value like latest or 18.04!
  • You used multiple colons like ubuntu:18.04:2 or ubuntu:ubuntu:18.04. Use only a single colon in the image name!
  • You mixed up the order of command line arguments, so another argument is being interpreted as the image name. Check the syntax of your docker command, e.g. docker run and compare some examples with your command.
Posted by Uli Köhler in Container, Docker

How to get schema of SQLite3 table in Python

Also see How to show table schema for SQLite3 table on the command line

Use this function to find the table schema of a SQLite3 table in Python:

def sqlite_table_schema(conn, name):
    """Return a string representing the table's CREATE"""
    cursor = conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", [name])
    sql = cursor.fetchone()[0]
    cursor.close()
    return sql

Usage example:

print(sqlite_table_schema(conn, 'commands'))

Full example:

#!/usr/bin/env python3
import sqlite3
conn = sqlite3.connect('/usr/share/command-not-found/commands.db')

def sqlite_table_schema(conn, name):
    cursor = conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", [name])
    sql = cursor.fetchone()[0]
    cursor.close()
    return sql

print(sqlite_table_schema(conn, 'commands'))

which prints

CREATE TABLE "commands" 
           (
            [cmdID] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
            [pkgID] INTEGER NOT NULL,
            [command] TEXT,
            FOREIGN KEY ([pkgID]) REFERENCES "pkgs" ([pkgID])
           )

 

 

Posted by Uli Köhler in Python, SQLite

How to fix SQLite3 Python ‘Incorrect number of bindings supplied. The current statement uses 1, … supplied’

Problem:

You are trying to run a simple SQL query with placeholders on a SQLite3 database, e.g.:

name = "mytable"
conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", name)

But you get an exception like this:

---------------------------------------------------------------------------
ProgrammingError                          Traceback (most recent call last)
<ipython-input-55-e385cf40fd72> in <module>
      1 name = "mytable"
----> 2 conn.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name=?;", name)

ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 7 supplied.

Solution:

You need to use a list as the second argument to conn.execute(...)!

Since you only gave the function a string, the string is being interpreted as list of characters.

In our example from above, you just need to wrap name in square brackets to read [name]:

name = "mytable"
conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", [name])
Posted by Uli Köhler in Python, SQLite
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Cookie settingsACCEPTPrivacy &amp; Cookies Policy