wokwi-features
wokwi-features copied to clipboard
Create new parts (chips, sensors, etc.) with custom logic
Make it possible to create custom parts and program your own logic:
- Define the pins for the part (e.g., for an I2C sensor: GND, VCC, SCL, SDA, INT)
- Write some code to implement the logic for the part
- Load this part into Wokwi and use it in the simulation.
I've done some prototyping, and one way to implement this in a secure and performant way is to use AssemblyScript together with Web Assembly.
Initial thoughts about the API for creating custom parts:
- Keep the function names similar to Arduino (e.g. digitalRead/digitalWrite/pinMode)
- Make it easy to include standard protocols (such as UART, I2C, SPI)
- The first version should focus in digital simulation, as the Analog part of the simulator is not very mature at this time.
Here's a proposal of what the code for a simple part (pulse counter with an I2C interface) might look like:
import { createI2CDevice, digitalWatch, I2CDevice, I2CPins, registerChip } from 'wokwi-api';
export enum Pins {
GND,
VCC,
SCL,
SDA,
PULSE,
}
enum Events {
PulseIn,
}
const ADDRESS: u8 = 0x22;
export class CounterChip implements I2CDevice {
private counter: u32;
private byteIndex: u8;
constructor() {
this.counter = 0;
this.byteIndex = 0;
createI2CDevice(this, new I2CPins(Pins.SCL, Pins.SDA), ADDRESS);
digitalWatch(Pins.PULSE, Events.PulseIn);
}
i2cConnect(): boolean {
this.byteIndex = 0;
return true; /* ack */
}
i2cReadByte(): u8 {
const shiftAmount = this.byteIndex++ * 8;
return u8(this.counter >> shiftAmount);
}
i2cWriteByte(value: u8): void {
// Writing any value just resets the counter
this.counter = 0;
}
i2cDisconnect(): void {
// do nothing
}
onEvent(event: i32, data: i32): void {
switch (event) {
case Events.PulseIn:
/* data holds the new pin value: 1 for rising edge */
if (data) {
this.counter++;
}
break;
}
}
}
registerChip('i2c-counter', CounterChip);
And another example - HC-SR04 Ultrasonic sensor (for now, with a fixed distance):
import { addClockEvent, digitalWatch, digitalWrite, HIGH, LOW, OUTPUT, pinMode } from './wokwi-api';
const distance = 300;
enum Pins {
VCC,
GND,
ECHO,
TRIG,
}
enum Events {
TrigChanged,
StartEcho,
EndEcho,
}
export class UltrasonicSensor {
constructor() {
digitalWatch(Pins.TRIG, Events.TrigChanged);
pinMode(Pins.ECHO, OUTPUT);
digitalWrite(Pins.ECHO, LOW);
}
onTrigChanged(value: boolean): void {
if (!value) {
const us = 1000;
const echoDelay = 300 * us;
const echoTime = Math.round(distance * 58.82 * us);
addClockEvent(echoDelay, Events.StartEcho);
addClockEvent(echoDelay + echoTime, Events.EndEcho);
}
}
onEvent(event: i32, data: i32): void {
switch (event) {
case Events.TrigChanged:
this.onTrigChanged(bool(data));
break;
case Events.StartEcho:
digitalWrite(Pins.ECHO, HIGH);
break;
case Events.EndEcho:
digitalWrite(Pins.ECHO, LOW);
break;
}
}
}
Yes please! ❤️
Started working on this and uploaded an early prototype so users can start playing around and share their feedback.
Here's a quick demo project: https://wokwi.com/projects/327144279206003284 Press "F1" and select "Create a custom C chip (alpha)", then run the simulation to see the Arduino sketch communicating with the custom I2C chip. The chip logic is defined in "i2c-counter.chip.c", and the pinout in "i2c-counter.chip.json".
And a google doc with further explanations: https://link.wokwi.com/custom-chips-alpha
Can I suggest the new part creating uses the Fritzing images and pin maps to speed up device creation?
@sjamesparsonsjr that suggestion may fit better in #302
Hi,
This is great. I have successfully created a simple chip based on the i2c-counter example.
Is it possible to create more than one chip for each system model? Can a created chip be 'saved' to be used for other simulations?
I hope the development continues!
Thanks for the feedback!
It's possible to create multiple instance of each chip type. Here's a recent example with 2 copies of the same chip:
https://wokwi.com/projects/335750100024296020
What do you mean by "saving" custom chips for using in other simulation?
Hi, Thanks for the reply. The example given shows the chip defined as "chip-bounce"; where is this definition made? Can "chip-bounce" be saved as an entity to be used later, much like the the 'new parts' list on the simulation panel? Diagram.json shows some interesting parts not shown in the 'new parts' drop down. Is there a list of these parts? (I came across an example using the Adafruit SSD1306 OLED display, wokwi-ssd1306, also not listed in the 'add new part' drop-down menu). I would really like to use the chip creation feature and hope these questions aren't too naive. Thanks again.
The example given shows the chip defined as "chip-bounce"; where is this definition made? Can "chip-bounce" be saved as an entity to be used later, much like the the 'new parts' list on the simulation panel?
The definition is implicitly made whenever you have a pair of "whatever.chip.json" and "whatever.chip.c" files. Right now, the chips are saved along with the project, but we're looking into a way to make them separate entities that can be imported into a project (much like you can import Arduino libraries using the Library Manager).
The current solution we're looking into is hosting custom chips on GitHub - you create a github repo with the custom chip source code and definition, and then you'll be able to submit the repo to a central Wokwi Chip registry, and users will be able to pull chips from this registry. Still working out the details.
Diagram.json shows some interesting parts not shown in the 'new parts' drop down. Is there a list of these parts? (I came across an example using the Adafruit SSD1306 OLED display, wokwi-ssd1306, also not listed in the 'add new part' drop-down menu).
These parts aren't officially supported. Some are incomplete (e.g. wokwi-serial-port - see #149), or deprecated (like wokwi-ssd1306), and some just need some documentation and perhaps a bit of refactoring (e.g. #240).
I'm curious, what are you using the custom chips for?
Thanks for the information. A GitHub chip repository seems very reasonable. I will await developments.
The chips are sensors for a project (a model submarine!) I want to build; the sensors need to interact with one-another. For example a sensor determining the water level in ballast tanks needs to affect the output of (say) an MPU6050 accelerometer so feedback can adjust pitch (level) of the sub. Currently I think the outputs have to be provided independently with sliders. Is the code available for the officially supported chips?
Thanks again.
The chips are sensors for a project (a model submarine!) I want to build
Sounds like a cool use-case! Do you have some models?
Is the code available for the officially supported chips?
Only for a few of them, e.g. the ILI9163 Display Driver. I guess you are looking for the code of the MPU6050? Is there anything else?
Not sure if this is the appropriate place to put this, but I was thinking that it would be cool to be able to select several predefined components and click a button that allowed you to make your own custom component. So , for example, If I m working with a lot of LEDs and their associated resistors, I would like to be able to generate an LED and connect it to a resistor, then with both items selected, define a custom component that would only show up locally in my dev. environment.
Then every time I needed one of these, I could grab it from my + button under My Custom Components and voila it would appear just how I had wired it. This would be super easy to code and the combined elements as their own custom component would have all of the attributes that were not already defined. In other words, it would have two pins (the two open pins) to connect to as well as the resistance on the resistor, the color on the LED. When I generate my custom component made of other components, that stuff would automatically be exposed. Maybe that's a different request, but just in case.
Maybe that's a different request, but just in case.
Yeah, that sounds like a new feature request - some kind of "modules" library. One way to sort-of achieve this now is to have a project with your common "modules", and then you can select several parts, copy them, and paste them into another projects. They'll be copied along with all the internal connections. Anyway, feel free to open a new feature request!
Update: the Custom Chip API is now getting into a beta phase. There will probably be some minor changes, but I think we're already clear on the general direction.
You can view the current API reference here: https://gist.github.com/urish/f9129d3d34ffd557eccf354907663051, and we expect to shortly migrate it to https://docs.wokwi.com.
Here's a bunch of examples for custom chips, showing what you can do with the current API:
- Digital Inverter
- XOR gate
- SPI Chip – Implements a basic ROT13 cipher
- I2C Chip – Simple counter interrupt output
- UART Chip – Implements a basic ROT13 cipher
- Timer Chip – Showing how to use the Timer API
- LM75A Chip – I2C digital temperature sensor
- Framebuffer chip – Shows how to implement a custom display driver chip
- IL9163 Display Driver – 128x128 color LCD display chip
- I2C Keypad Driver Example (by Yewolf)
- CD4051B Multiplexer Example (by Chris Schmidt)
Nice work!
The API documentation is clear, but it lacks information about the chip.json structure (display, controls).
BTW: in doc is analog example, but not here.
And my propositions:
- It should be possible to define the appearance of the element. For example:
- by handling wokwi-elements format,
- selecting an case (e.g .: DIP_n_, SOP_n_, TQFP_n_, TO-98, TO-225, TO-220),
- uploading an SVG file,
- Are you planning to create a custom-element library?
//edit:
You wrote:
It's possible to create multiple instance of each chip type. Here's a recent example with 2 copies of the same chip:
Is possibl eto create multiple different chips? (eg XOR CD4030 + NAND MC14093B )
Thanks for the feedback @bato3!
It should be possible to define the appearance of the element. For example:
Yeah, the details aren't clear yet, but this might be part of #302. Probably uploading an SVG file and defining the pins.
Are you planning to create a custom-element library?
There'll probably be some way to submit your custom chips and for other users to add them. Perhaps through GitHub. Still thinking of possible ways to accomplish this.
Is possibl eto create multiple different chips?
Yes, you can have many chip types in a single project, and multiple instances of each chip type.
Are you planning to create a custom SVG element resource that WOKWI loads and all SVGS can simply reference? Like what you do with the "hole" symbol on your current SVG artwork?
Ideally, given a default library set, someone could create any svg and include your resources for "pins" or solder points or connectors of any sort and that SVG would be ready to be added to the layout, including accessibility to connections. The only thing it would require for simulation would be the underlying code which would benefit from the standardization of the connector SVG resources.
By standardizing every connector type and perhaps some common display types like (on board LEDs), simple hooks in the API would help with the logic part. But even before the logic part was not done, having the SVG with standardized components would enable layout and connections immediately. Upon adding a custom component all of the "pin" SVG symbols would be enabled for connections, for example. This might make it easier to debug upon running the simulation. Ill check out 302 to see if its covered there. Great work on custom elements. thanks
Probably for starters, the user will just provide the complete SVG. To make things simple. Then we'll see how to evolve it based on how users will use it and the feedback we get (that's how Wokwi goes in general)
Update: We have a proof-of-concept of creating custom chips using the Rust language. Here's an example of an inverter:
https://wokwi.com/projects/346597452510397012
New docs for custom chips: https://docs.wokwi.com/chips-api/getting-started
Also, a new example of a chip hosted in GitHub repo: https://github.com/wokwi/inverter-chip
Thank you for the progress on this amazing addition, Can I confirm that the custom chip functionality isn't currently supported in Visual Studio? (or do i need to put the chip definitions somewhere other than root)
Can I confirm that the custom chip functionality isn't currently supported in Visual Studio?
It is supported in Visual Studio Code. Please take a look at the documentation: https://docs.wokwi.com/vscode/project-config#custom-chips
Is the documentation about this clear or does it need any improvements?
Ah, perfect, it seems that once again I failed to locate the relevant documentation.
It took me a second to work out that its possible to replace the 'wasm' with the 'c' file, and now it works perfectly. I think the thing that tripped me up was the requirement to define the chip in the '.toml' file, instead of the web version auto detecting, though its added ability to add the chip definitions to sub folders is really neat.
Keep up the amazing work
I may have spoke too soon on it working with a *.chip.c file, it seems to hang on the 'Loading project...' message. I will convert the chips over to a wasm and load them instead :)
Yeah, it doesn't know how to compile things - you have to feed it with binaries :)
Do you need any assistance in converting the chips to wasm?
I will see what I can do for a little bit, using the existing examples, and try to convert the 'eeprom_custom_chip_test' example into wasm.
I will let you know in an hour if i'm stuck. :)
Ive had some luck using your example for an inverter and the EEPROM example, to compile the wasm at the following repo https://github.com/alextrical/wokwi-24C01-custom-chip Oddly i had issues getting the Build part of the Workflow to trigger ("github.event_name == 'push'" wasn't triggering when pushing from GitHub Desktop) and then the "ncipollo/release-action" failed with the following error 'Error undefined: No tag found in ref or input!'
Ive managed to force it through to a release, and can now see the desired chip.zip file :)
edit: all fixed, I wasn't using "tags" in the push, now I have done that it works without having to edit the Workflow. The error was pretty clear
New UI to easily create custom chips and add them to your project:
Also, updated the documentation:
- Updated getting started guide
- New Chip Definition JSON reference
New video tutorial - how to create custom chips, 3 examples in 15 minutes
https://youtu.be/yzdCS3A4DvU
Another video tutorial: Creating an I2C I/O expander chip from scratch in Wokwi, using the Custom Chips API
This is really great! One question, is or will there be a searchable part library, where i can checkout what other users did? Just so I don't have to reinvent the wheel when it comes to common chips.