added i2c-test branch

This commit is contained in:
Skot Croshere 2023-01-16 17:55:16 -05:00
parent 6db109a29c
commit c6448abcd8
12 changed files with 380 additions and 29 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# Configuration files
sdkconfig
sdkconfig.old
# Production folder
build/
# HTML documentation
html_doc/
components/components/*

6
CMakeLists.txt Executable file
View File

@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(I2c_test)

8
Makefile Executable file
View File

@ -0,0 +1,8 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := i2c-simple
include $(IDF_PATH)/make/project.mk

2
main/CMakeLists.txt Executable file
View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "i2c_simple_main.c" "led_controller.c" "DS4432U.c"
INCLUDE_DIRS ".")

75
main/DS4432U.c Normal file
View File

@ -0,0 +1,75 @@
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
//DS4432U+ -- Adjustable current DAC for use with the TPS40305 voltage regulator
//address: 0x90
#define DS4432U_SENSOR_ADDR 0x48 //Slave address of the DS4432U+
#define DS4432U_OUT0_REG 0xF8 //register for current output 0
#define DS4432U_OUT1_REG 0xF9 //register for current output 1
static const char *TAG = "DS4432U.c";
/**
* @brief i2c master initialization
*/
esp_err_t i2c_master_init(void) {
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
/**
* @brief i2c master delete
*/
esp_err_t i2c_master_delete(void) {
return i2c_driver_delete(I2C_MASTER_NUM);
}
/**
* @brief Read a sequence of I2C bytes
*/
static esp_err_t register_read(uint8_t i2c_address, uint8_t reg_addr, uint8_t *data, size_t len) {
return i2c_master_write_read_device(I2C_MASTER_NUM, i2c_address, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
}
/**
* @brief Write a byte to a I2C register
*/
// static esp_err_t register_write_byte(uint8_t i2c_address, uint8_t reg_addr, uint8_t data) {
// int ret;
// uint8_t write_buf[2] = {reg_addr, data};
// ret = i2c_master_write_to_device(I2C_MASTER_NUM, i2c_address, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
// return ret;
// }
void DS4432U_read(void) {
uint8_t data[3];
/* Read the DS4432U+ WHO_AM_I register, on power up the register should have the value 0x00 */
ESP_ERROR_CHECK(register_read(DS4432U_SENSOR_ADDR, DS4432U_OUT1_REG, data, 1));
ESP_LOGI(TAG, "DS4432U+ OUT1 = 0x%02X", data[0]);
}

10
main/DS4432U.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef DS4432U_H_
#define DS4432U_H_
#include "driver/i2c.h"
esp_err_t i2c_master_init(void);
esp_err_t i2c_master_delete(void);
void DS4432U_read(void);
#endif /* DS4432U_H_ */

17
main/Kconfig.projbuild Executable file
View File

@ -0,0 +1,17 @@
menu "Example Configuration"
config I2C_MASTER_SCL
int "SCL GPIO Num"
default 6 if IDF_TARGET_ESP32C3
default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
GPIO number for I2C Master clock line.
config I2C_MASTER_SDA
int "SDA GPIO Num"
default 5 if IDF_TARGET_ESP32C3
default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
GPIO number for I2C Master data line.
endmenu

3
main/component.mk Executable file
View File

@ -0,0 +1,3 @@
#
# Main Makefile. This is basically the same as a component makefile .
#

73
main/i2c_simple_main.c Executable file
View File

@ -0,0 +1,73 @@
/* i2c - Simple example
Simple I2C example that shows how to initialize I2C
as well as reading and writing from and to registers for a sensor connected over I2C.
For other examples please check:
https://github.com/espressif/esp-idf/tree/master/examples
See README.md file to get detailed usage of this example.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "led_controller.h"
#include "DS4432U.h"
static const char *TAG = "i2c-test";
//INA260 -- Power meter
//address: 0x40
#define INA260_SENSOR_ADDR 0x40 //Slave address of the INA260
#define INA260_MANFID_REG 0xFE //should be 0x5449
//EMC2101 -- Fan and temp sensor controller
//address: 0x4C
#define EMC2101_SENSOR_ADDR 0x4C //Slave address of the EMC2101
#define EMC2101_PRODUCTID_REG 0xFD //should be 0x16 or 0x28
void app_main(void) {
//test the LEDs
ESP_LOGI(TAG, "Init LEDs!");
initLEDs();
// gpio_set_level(LEDX_R, 1);
// gpio_set_level(LEDZ_R, 1);
ledc_init();
led_set();
ESP_ERROR_CHECK(i2c_master_init());
ESP_LOGI(TAG, "I2C initialized successfully");
DS4432U_read();
// /* Read the EMC2101 WHO_AM_I register, on power up the register should have the value 0x16 or 0x28 */
// ESP_ERROR_CHECK(register_read(EMC2101_SENSOR_ADDR, EMC2101_PRODUCTID_REG, data, 1));
// ESP_LOGI(TAG, "EMC2101 PRODUCT ID = 0x%02X", data[0]);
// /* Read the INA260 WHO_AM_I register, on power up the register should have the value 0x5449 */
// ESP_ERROR_CHECK(register_read(INA260_SENSOR_ADDR, INA260_MANFID_REG, data, 2));
// ESP_LOGI(TAG, "INA260 MANF ID = 0x%02X%02X", data[0], data[1]);
// /* Read the DS4432U+ WHO_AM_I register, on power up the register should have the value 0x00 */
// ESP_ERROR_CHECK(register_read(DS4432U_SENSOR_ADDR, DS4432U_OUT1_REG, data, 1));
// ESP_LOGI(TAG, "DS4432U+ OUT1 = 0x%02X", data[0]);
// /* Demonstrate writing by reseting the MPU9250 */
// ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_PWR_MGMT_1_REG_ADDR, 1 << MPU9250_RESET_BIT));
ESP_ERROR_CHECK(i2c_master_delete());
ESP_LOGI(TAG, "I2C unitialized successfully");
}

126
main/led_controller.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include "esp_err.h"
#include "driver/ledc.h"
#include "driver/gpio.h"
//LEDS
#define LEDX_R GPIO_NUM_35
#define LEDX_G GPIO_NUM_36
#define LEDX_B GPIO_NUM_37
#define LEDZ_R GPIO_NUM_38
#define LEDZ_G GPIO_NUM_39
#define LEDZ_B GPIO_NUM_40
void initLEDs(void) {
gpio_set_direction(LEDX_R, GPIO_MODE_OUTPUT);
gpio_set_direction(LEDX_G, GPIO_MODE_OUTPUT);
gpio_set_direction(LEDX_B, GPIO_MODE_OUTPUT);
gpio_set_direction(LEDZ_R, GPIO_MODE_OUTPUT);
gpio_set_direction(LEDZ_G, GPIO_MODE_OUTPUT);
gpio_set_direction(LEDZ_B, GPIO_MODE_OUTPUT);
gpio_set_level(LEDX_R, 0);
gpio_set_level(LEDX_G, 0);
gpio_set_level(LEDX_B, 0);
gpio_set_level(LEDZ_R, 0);
gpio_set_level(LEDZ_G, 0);
gpio_set_level(LEDZ_B, 0);
}
void ledc_init(void) {
// Prepare and then apply the LEDC PWM timer configuration
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = LEDC_TIMER_12_BIT, // Set duty resolution to 12 bits
.freq_hz = 5000, // Set output frequency at 5 kHz
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
// Prepare and then apply the LEDC PWM channel configuration
ledc_channel_config_t ledc_channel0 = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 35, // Define the output GPIO
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel0));
ledc_channel_config_t ledc_channel1 = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_1,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 36, // Define the output GPIO
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel1));
ledc_channel_config_t ledc_channel2 = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_2,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 37, // Define the output GPIO
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel2));
ledc_channel_config_t ledc_channel3 = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_3,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 38, // Define the output GPIO
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel3));
ledc_channel_config_t ledc_channel4 = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_4,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 39, // Define the output GPIO
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel4));
ledc_channel_config_t ledc_channel5 = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_5,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 40, // Define the output GPIO
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel5));
}
void led_set(void) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 3000)); //r
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 1000)); //g
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, 0)); //b
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_3, 3000)); //r
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_4, 1000)); //g
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_5, 0)); //b
// Update duty to apply the new value
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_3));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_4));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_5));
}

8
main/led_controller.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef LED_CONTROLLER_H_
#define LED_CONTROLLER_H_
void initLEDs(void);
void ledc_init(void);
void led_set(void);
#endif /* LED_CONTROLLER_H_ */

70
readme.md Normal file → Executable file
View File

@ -1,37 +1,49 @@
## ESP-Miner
# I2C Simple Example
ESP-Miner is bitcoin miner software designed to run on the ESP32. It mines on ASICs such as the Bitmain BM1397. The [BitaxeMax](https://github.com/skot/bitaxe/tree/max) is a handy board for this!
(See the README.md file in the upper level 'examples' directory for more information about examples.)
![esp-miner block diagram](doc/diagram.png)
## Overview
## Architecture
- Uses the ESP-IDF Framework, which is based on FreeRTOS (no Linux involved)
- Uses the ESP32 WiFi to connect to the network
- The ESP32 is provisioned to the local WiFi over BLE using ESP SmartConfig
This example demonstrates basic usage of I2C driver by reading and writing from a I2C connected sensor:
### Firmware
- ESP-Miner connects to and verifies the attached mining ASIC.
- Setting the baud rate, hashing frequency, and filling in some other mystery registers
- This startup sequence for the BM1387 and BM1397 can be found in cgminer the Kano edition in [driver-gekko.c](https://github.com/kanoi/cgminer/blob/master/driver-gekko.c)
If you have a new I2C application to go (for example, read the temperature data from external sensor with I2C interface), try this as a basic template, then add your own code.
- ESP-Miner connects to your pool or stratum server and subscribes to get the latest work.
- This is done with [JSON-RPC](https://www.jsonrpc.org)
- Via the [Stratum](https://braiins.com/stratum-v1/docs) protocol
- [cJSON](https://github.com/DaveGamble/cJSON) seems like a good embedded library for doing this.
- ESP-Miner gets the latest work and formats it to be sent to the mining ASIC.
- There isn't much change here except for computing the midstates, and shifting some bytes around
- Beware of endianess!
- How do we do this? Examples in cgminer Kano edition.
- I have started on this.. [check this](nm1397_protocol.md)
- ESP-Miner sends this work to the mining ASIC over serial.
## How to use example
- The Mining ASIC will report back any when it finds a hash over the difficulty (which)?
- The catch here is that if it doesn't find a hash over the difficulty, it will not report back at all. So you need to keep track of the hashing frequency and the time so that you can send a new block header to be hashed.
### Hardware Required
- ESP-Miner will report back to the pool over Stratum the results of mining.
To run this example, you should have one ESP32, ESP32-S or ESP32-C based development board as well as a MPU9250. MPU9250 is a inertial measurement unit, which contains a accelerometer, gyroscope as well as a magnetometer, for more information about it, you can read the [PDF](https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf) of this sensor.
- All of the administrative stuff of running a miner like;
- Set the BM1397 core voltage and current.
- check the fan speed
- check the BM1397 temperature
- optimize the hashing frequency and core voltage for max efficiency
#### Pin Assignment:
**Note:** The following pin assignments are used by default, you can change these in the `menuconfig` .
| | SDA | SCL |
| ---------------- | -------------- | -------------- |
| ESP I2C Master | I2C_MASTER_SDA | I2C_MASTER_SCL |
| MPU9250 Sensor | SDA | SCL |
For the actual default value of `I2C_MASTER_SDA` and `I2C_MASTER_SCL` see `Example Configuration` in `menuconfig`.
**Note: ** Theres no need to add an external pull-up resistors for SDA/SCL pin, because the driver will enable the internal pull-up resistors.
### Build and Flash
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
```bash
I (328) i2c-simple-example: I2C initialized successfully
I (338) i2c-simple-example: WHO_AM_I = 71
I (338) i2c-simple-example: I2C unitialized successfully
```
## Troubleshooting
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)