[應用] 在 ESP32 Audio 開發板的 VoIP 範例

開發板介紹

        安信可公司(Ai-Thinker)基於 ESP32 晶片推出一塊具有語音功能的 ESP32 Audio Kit 開發板,簡稱 ESP32-A1S,它與原廠的 ESP32 Lyrat 開發板都使用同一套 ESP-ADF SDK 軟體,但是開發板的電路有些差異,底層的驅動程式需要替換才能順利開發。

        首先,最大的差異在 ESP32-A1S 語音編碼晶片採用 AC101,不過晶片被封裝在 ESP32 模組上,所以我們在開發板上面看不到這顆晶片,然而 ESP32 Lyrat 板採用 ES8388 晶片,因此在 ESP-ADF 中語音編碼的驅動程式需要更替。另外,其他不一樣的地方都在 GPIO 接腳的連接上,整理後,如下表所示,我們需要調整 ADF 底層的 HAL 和 Board 的配置,SDK 才能正常使用。

表一:ESP32-Lyrat 與 Audio Kit 開發板的差異

        第一步,下載 ESP-ADF。在 VS Code 開發環境下[1],按 F1 後,選取 "Install ESP-ADF",VS Code 會自動從 GitHub 下載,並安裝 ADF 開發套件。如果是使用 ESP32-Lyrat 板子,可以直接跳到第四步,創建範例開始開發了。使用 ESP32-A1S 板子前,需要調整一下底層代碼,接續前面動作,我們從 GitHub 下載 A1S 的驅動程式,ESP32-A1S-AudioKit 程式碼,其目錄結構與 ADF 一樣,方便我們相互比對兩者差異。

        第二步,到 \esp-adf\components\audio_hal\driver 目錄下,將下載 A1S 裡的 AC101 驅動程式放進來。接著,要將 ac101 目錄和 ac101.c 加到 CMakeLists.txt 文件,同樣也要加到 component.mk 文件裡,這樣編譯過程就會把 AC101 驅動程式加進來編譯了。

        第三步,我們再到 \esp-adf\components\audio_board\lyrat_v4_3 目錄下(因為我們沒想要在 menuconfig 裡新增 A1S 配置,打算借用 lyrat 原配置),將 board.c、board.h、board_def.h、board_pins_config.c 更換成 A1S 的,其中 board_def.h 裡面是 GPIO 腳位的對應,請比對上面圖表的對應,修改成正確的 IO 編號。在 INPUT_KEY 結構中定義按鈕的型態,分 BUTTON TOUCH,我們在未來使用一些範例時要改為 BUTTON (對於 A1S 而言),因為可能之後使用 VoIP 範例時會遇上問題。 

        第四步,我們要驗證上面更換的動作無誤,從 ADF 裡創建一個範例來驗證驅動程式能運作。按 F1 後,選取 "Show Examples Projects",找 play_mp3_control 這個範例來試試看。編譯並燒錄後,我們從耳機孔能聽到音樂的話,代表驅動程式更換成功。開發板上的 Key2~Key6 按鈕對應的功能分別為 Mode、Set、Play、Vol+、Vol-,我們也可以檢驗按鈕功能是否正常,代表 GPIO 腳位對應正確了。

範例 VoIP

        在 ESP-ADF 提供了 VoIP 範例程式碼,按 F1 後,選取 "Show Examples Projects",找到 VoIP 這個範例後並創建目錄。VS Code 載入這個範例後,我們先打開 menuconfig 配置,如下圖所示,設定欲連線 WiFi AP 的名稱與密碼,Audio_HAL 選定 "Lyrate 4.3",前段我們說過借用這個配置, 底層的驅動程式已經被更換了。

        接下來,SIP URI 設定開發板的 SIP 帳號將會註冊到哪一個服務器上,註冊成哪個分機與註冊的密碼。這裡的SIP URI 格式為  transport://user:password@serverIP:port,transport 指的是 SIP 連線方式是 UDP 或 TCP,user:password 指的是註冊的分機號和密碼,serverIP 指的是欲註冊的服務器 IP 位址,port 指的是服務器上監聽 SIP 的端口。我在這邊設定 udp://1002:1234@192.168.1.205:5060,代表 SIP 通訊協定採用 UDP 連線方式,監聽端口為 5060,註冊到服務器 192.168.1.205 上面的分機 1002,註冊密碼為 1234。

圖一:menuconfig 配置

        當我們設定 menuconfig 配置後,可以首次編譯,看看是否成功。如果成功,燒錄 .bin 到板子上。另外,第一次載入 VoIP 這個範例時,還要燒錄一個音檔(audio-esp.bin)到板子上,這個音檔的內容主要是鈴聲、服務器連接的提示音....等,VoIP 應用程式會撥放這個音檔裡的內容,至於燒錄的指令,請參考 README.md。

        在 VoIP 這個應用,開發板上的 Key1~Key6 按鈕對應的功能分別為 MuteMode、Set、Play、Vol+ 和 Vol-,不過 Mute 按鍵的功能似乎在 A1S 板並不成功。Mode 鍵是掛斷或取消,Play 鍵是接聽或呼叫,Vol+ 和 Vol- 就是音量鍵。圖二說明 Play 按鍵可當接聽或撥號,目前程式碼設定的撥號分機號為 101,這個部分可以自行修改調整。

圖二:Play 按鍵的功能代碼

        最後,我們需要準備一個 SIP PBX 服務器和另一個手機 SIP app,這樣才能完成 VoIP 的系統測試。服務器可以選擇安裝 FreeSwitch 或 Asterisk (這裡我安裝的是 FreeSwitch 1.8.7),在手機安裝一個 Linphone APP,並註冊到服務器上。從 Linphone 撥打 1002,ESP-A1S 板子會聽到鈴聲,按下 Key4 (Play) 接聽,VoIP 通訊雙向就連通了。



參考資料

留言

gwansyan說…
SIP PBX 服務器 是安裝在筆電嗎?
gwansyan說…
編繹後產生的錯,請指導

implicit declaration of function 'INPUT_KEY_DEFAULT_INFO'; did you mean 'ETH_PHY_DEFAULT_CONFIG'? [-Werror=implicit-function-declaration]

'INPUT_KEY_NUM' undeclared (first use in this function)

passing argument 3 of 'input_key_service_add_key' makes integer from pointer without a cast [-Wint-conversion]
漢亞科技說…
It's Key_Pad ..... 'INPUT_KEY_NUM' is defined in "board_def.h" under \esp\esp-adf\components\audio_board\
漢亞科技說…
SIP PBX 服務器 是安裝在筆電嗎? Yes, softswitch..... such as FreeSwitch.
匿名說…
in vscode monitoring show
++++++++++++++++++++++++++++++++++++++++++++++++++
REGISTER sip:604@192.168.43.202:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.43.96:15849;branch=z9hG4bK-773438890;rport
From: ;tag=-1505150429
To:
Contact:
Max-Forwards: 70
Call-ID: 696A5897BE7245B4A0080AB89470A451884FF94558ED
CSeq: 7 REGISTER
Expires: 3600
User-Agent: ESP32 SIP/2.0
Content-Length: 0
Allow: INVITE, ACK, CANCEL, BYE, UPDATE, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE
Supported: replaces, norefersub, extended-refer, timer, X-cisco-serviceuri
Allow-Events: presence, kpml


I (43977) SIP: [1970-01-01/00:00:21]=======================>>
I (43997) SIP: [1970-01-01/00:00:21]<<=====READ 0591 bytes==
I (43997) SIP:

SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.43.96:15849;branch=z9hG4bK-773438890;rport=15849
From: ;tag=-1505150429
To: ;tag=9Kr5SpvFUt6Zp
Call-ID: 696A5897BE7245B4A0080AB89470A451884FF94558ED
CSeq: 7 REGISTER
User-Agent: FreeSWITCH
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
WWW-Authenticate: Digest realm="192.168.43.202", nonce="8cbf35bf-61b8-4557-a086-dd49f2926a1e", algorithm=MD5, qop="auth"
Content-Length: 0


I (44047) SIP: [1970-01-01/00:00:21]<<======================
I (44047) SIP: Required authentication
I (44057) SIP: [1970-01-01/00:00:21]=======WRITE 0836 bytes>>
I (44057) SIP:

REGISTER sip:604@192.168.43.202:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.43.96:15849;branch=z9hG4bK-216679480;rport
From: ;tag=-747012202
To:
Contact:
Max-Forwards: 70
Call-ID: 696A5897BE7245B4A0080AB89470A451884FF94558ED
CSeq: 8 REGISTER
Expires: 3600
User-Agent: ESP32 SIP/2.0
Content-Length: 0
Allow: INVITE, ACK, CANCEL, BYE, UPDATE, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE
Supported: replaces, norefersub, extended-refer, timer, X-cisco-serviceuri
Allow-Events: presence, kpml
Authorization: Digest username="604", realm="192.168.43.202", nonce="8cbf35bf-61b8-4557-a086-dd49f2926a1e", uri="sip:192.168.43.202:5060", response="5bd697163c9f6d63490021e2c0a37280", algorithm=MD5, nc=00000001, cnonce="72229f753174d8a3", qop="auth"


I (44137) SIP: [1970-01-01/00:00:21]=======================>>
I (44197) SIP: [1970-01-01/00:00:21]<<=====READ 0465 bytes==
I (44197) SIP:

SIP/2.0 403 Forbidden
Via: SIP/2.0/UDP 192.168.43.96:15849;branch=z9hG4bK-216679480;rport=15849
From: ;tag=-747012202
To: ;tag=aXHyUHDKr3vjj
Call-ID: 696A5897BE7245B4A0080AB89470A451884FF94558ED
CSeq: 8 REGISTER
User-Agent: FreeSWITCH
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Content-Length: 0


I (44237) SIP: [1970-01-01/00:00:21]<<======================
E (44247) SIP: Error register device
W (44247) SIP: CHANGE STATE FROM 1, TO 0, :func: sip_register:1682
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

in freswitch :
sofia_reg.c:1806 SIP auth failure (REGISTER) on sofia profile 'internal' for [604@192.168.43.202] from ip 192.168.43.96
漢亞科技說…
Authorization: Digest username="604" <---- did you create ext 604 in freeswitch?
In freeswitch, default ext 1000 ~ 1009, password is 1234. You study freeswitch config in vars.xml, take a look at the "directory" folder.....
匿名說…
yes, registering 604,
other using softphone 600 and 601 work weel using microsip and zoiper,
or problem in ESP-adf voip example?
匿名說…
hi bro, how to solved! i install vscode after select esp-idf 3.3 get it :
[Error: non zero exit code 2 usage: idf.py [-h] [-p PORT] [-b BAUD] [-C PROJECT_DIR] [-B BUILD_DIR] [-G {Ninja,MinGW Makefiles}] [-n] [-v] [-D DEFINE_CACHE_ENTRY [DEFINE_CACHE_ENTRY ...]] [--no-ccache] {all,build,clean,fullclean,reconfigure,menuconfig,defconfig,confserver,size,size-components,size-files,bootloader,bootloader-clean,bootloader-flash,app,app-flash,efuse_common_table,efuse_custom_table,show_efuse_table,partition_table,partition_table-flash,flash,erase_flash,monitor,erase_otadata,read_otadata} [{all,build,clean,fullclean,reconfigure,menuconfig,defconfig,confserver,size,size-components,size-files,bootloader,bootloader-clean,bootloader-flash,app,app-flash,efuse_common_table,efuse_custom_table,show_efuse_table,partition_table,partition_table-flash,flash,erase_flash,monitor,erase_otadata,read_otadata} ...] idf.py: error: argument actions: invalid choice: 'set-target' (choose from 'all', 'build', 'clean', 'fullclean...
漢亞科技說…
Sorry, I have no idea. You may contact ESP-idf/adf support.
匿名說…
Work well now. but just microphone not work.
i am using esp32 v2.3 (e8388 audio chip)
我用 ESP_ADF 的 voip 例子烧掉了它。 SIP连接可以拨打电话,拨打电话时耳机有声音。 但 ESP 板上的麦克风不工作。

whats is wrong? mic not work but headphone sounding voice
gwansyan說…
編繹後產生的錯,請指導

implicit declaration of function 'INPUT_KEY_DEFAULT_INFO'; did you mean 'ETH_PHY_DEFAULT_CONFIG'? [-Werror=implicit-function-declaration]

'INPUT_KEY_NUM' undeclared (first use in this function)

passing argument 3 of 'input_key_service_add_key' makes integer from pointer without a cast [-Wint-conversion]


------------
在下面資料夾,按鍵定義如下,但編譯結果還是如上所述。



D:\Espressif\.espressif\esp-adf\components\audio_board\lyrat_v4_3

/*
* @Author: your name
* @Date: 2020-01-26 10:13:06
* @LastEditTime : 2020-01-28 19:24:42
* @LastEditors : Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \esp-adf\components\audio_board\aithinker\board_def.h
*/
/*
* ESPRESSIF MIT License
*
* Copyright (c) 2019
*
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/

#ifndef _AUDIO_BOARD_DEFINITION_H_
#define _AUDIO_BOARD_DEFINITION_H_

/* SD card related */
#define SD_CARD_INTR_GPIO GPIO_NUM_34
#define SD_CARD_INTR_SEL GPIO_SEL_34
#define SD_CARD_OPEN_FILE_NUM_MAX 5

#define HEADPHONE_DETECT GPIO_NUM_5
#define PA_ENABLE_GPIO GPIO_NUM_21

#define GREEN_LED_GPIO GPIO_NUM_22
#define BLUE_LED_GPIO GPIO_NUM_19

#define BUTTON_REC_ID GPIO_NUM_36
#define BUTTON_MODE_ID GPIO_NUM_13

/* Touch pad related */
#define TOUCH_SEL_SET GPIO_SEL_19
#define TOUCH_SEL_PLAY GPIO_SEL_23
#define TOUCH_SEL_VOLUP GPIO_SEL_18
#define TOUCH_SEL_VOLDWN GPIO_SEL_5

#define TOUCH_SET GPIO_NUM_19
#define TOUCH_PLAY GPIO_NUM_23
#define TOUCH_VOLUP GPIO_NUM_18
#define TOUCH_VOLDWN GPIO_NUM_5

extern audio_hal_func_t AUDIO_CODEC_AC101_CODEC_HANDLE;

#define AUDIO_CODEC_DEFAULT_CONFIG() { \
.adc_input = AUDIO_HAL_ADC_INPUT_LINE1, \
.dac_output = AUDIO_HAL_DAC_OUTPUT_ALL, \
.codec_mode = AUDIO_HAL_CODEC_MODE_BOTH, \
.i2s_iface = { \
.mode = AUDIO_HAL_MODE_SLAVE, \
.fmt = AUDIO_HAL_I2S_NORMAL, \
.samples = AUDIO_HAL_48K_SAMPLES, \
.bits = AUDIO_HAL_BIT_LENGTH_16BITS, \
}, \
};

#endif
漢亞科技說…
將原本在 lyrat_v4_3 board_def.h 的定義搬到 aithinker 裡面,先讓編譯能夠通過。

#define INPUT_KEY_NUM 6
#define INPUT_KEY_DEFAULT_INFO() { \
{ \
.type = PERIPH_ID_BUTTON, \
.user_id = INPUT_KEY_USER_ID_REC, \
.act_id = BUTTON_REC_ID, \
}, \
gwansyan說…
將原本在 lyrat_v4_3 board_def.h 的定義搬到 aithinker 裡面,先讓編譯能夠通過。

#define INPUT_KEY_NUM 6
#define INPUT_KEY_DEFAULT_INFO() { \
{ \
.type = PERIPH_ID_BUTTON, \
.user_id = INPUT_KEY_USER_ID_REC, \
.act_id = BUTTON_REC_ID, \
}, \

編繹後產生的錯,請指導

../main/voip_app.c: In function 'app_main':
../main/voip_app.c:413:58: error: 'fINPUT_KEY_NUM' undeclared (first use in this function); did you mean 'INPUT_KEY_NUM'?
input_key_service_add_key(input_ser, input_key_info, fINPUT_KEY_NUM);
^~~~~~~~~~~~~~
INPUT_KEY_NUM
../main/voip_app.c:413:58: note: each undeclared identifier is reported only once
for each function it appears in
ninja: build stopped: subcommand failed.
終端機處理序 "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command ninja " 已終止。結束代碼: 1。

在下面資料夾,按鍵定義如下。

D:\Espressif\.espressif\esp-adf\components\audio_board\lyrat_v4_3

* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/

#ifndef _AUDIO_BOARD_DEFINITION_H_
#define _AUDIO_BOARD_DEFINITION_H_

/* SD card related */
#define SD_CARD_INTR_GPIO GPIO_NUM_34
#define SD_CARD_INTR_SEL GPIO_SEL_34
#define SD_CARD_OPEN_FILE_NUM_MAX 5

#define HEADPHONE_DETECT GPIO_NUM_5
#define PA_ENABLE_GPIO GPIO_NUM_21

#define GREEN_LED_GPIO GPIO_NUM_22
#define BLUE_LED_GPIO GPIO_NUM_19

#define BUTTON_REC_ID GPIO_NUM_36
#define BUTTON_MODE_ID GPIO_NUM_13

/* Touch pad related */
#define TOUCH_SEL_SET GPIO_SEL_19
#define TOUCH_SEL_PLAY GPIO_SEL_23
#define TOUCH_SEL_VOLUP GPIO_SEL_18
#define TOUCH_SEL_VOLDWN GPIO_SEL_5

#define TOUCH_SET GPIO_NUM_19
#define TOUCH_PLAY GPIO_NUM_23
#define TOUCH_VOLUP GPIO_NUM_18
#define TOUCH_VOLDWN GPIO_NUM_5

#define INPUT_KEY_NUM 6
#define INPUT_KEY_DEFAULT_INFO() { \
{ \
.type = PERIPH_ID_BUTTON, \
.user_id = INPUT_KEY_USER_ID_REC, \
.act_id = BUTTON_REC_ID, \
}, \
};
extern audio_hal_func_t AUDIO_CODEC_AC101_CODEC_HANDLE;

#define AUDIO_CODEC_DEFAULT_CONFIG() { \
.adc_input = AUDIO_HAL_ADC_INPUT_LINE1, \
.dac_output = AUDIO_HAL_DAC_OUTPUT_ALL, \
.codec_mode = AUDIO_HAL_CODEC_MODE_BOTH, \
.i2s_iface = { \
.mode = AUDIO_HAL_MODE_SLAVE, \
.fmt = AUDIO_HAL_I2S_NORMAL, \
.samples = AUDIO_HAL_48K_SAMPLES, \
.bits = AUDIO_HAL_BIT_LENGTH_16BITS, \
}, \
};

#endif
漢亞科技說…
前一個留言,因為篇幅過多,我省略的部分定義內容。
找一找原本在 lyrat_v4_3 board_def.h 的定義,然後搬到 aithinker 裡面,讓編譯能夠通過
gwansyan說…
你好,
1。修改board_def.h內的按鍵定義後,編譯成功,謝謝。
2。透過UART燒錄.bin韌體,com埠是內定com3嗎?
3。第一次使用voip項目,必須燒錄音檔,但終端機出現以下訊息"[Errno 2] No such file or directory",請指導:
PS D:\adf-voip\voip> python $ADF_PATH/esp-idf/components/esptool_py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x210000 ./tools/audio-esp.bin

D:\Espressif\.espressif\tools\idf-python\3.8.7\python.exe: can't open file '/esp-idf/components/esptool_py/esptool/esptool.py': [Errno 2] No such file or directory
漢亞科技說…
COM port 不是內定 com3,要看你接到電腦上哪個USB孔上,com數字會不同的。
第一次使用必須燒錄音檔(就是鈴聲),請參考影片,細節需要看一看 README.md。
gwansyan說…
你好:
目前無法燒錄音檔(就是鈴聲),以下訊息顯示沒有此檔案或資料夾。我查詢資料夾是存在的,請指導,謝謝

D:\Espressif\.espressif\tools\idf-python\3.8.7\python.exe: can't open file '/esp-idf/components/esptool_py/esptool/esptool.py': [Errno 2] No such file or directory
JOJU說…
Hello, when I try to build play_mp3_control code after doing all steps above , An error occurred after compilation, please guide


error: 'GPIO_SEL_23' undeclared (first use in this function); did you mean 'GPIO_NUM_23'?
55 | #define TOUCH_SEL_PLAY GPIO_SEL_23
| ^~~~~~~~~~~

error: 'GPIO_SEL_18' undeclared (first use in this function); did you mean 'GPIO_NUM_18'?
56 | #define TOUCH_SEL_VOLUP GPIO_SEL_18

error: 'I2S_NUM_MAX' undeclared (first use in this
function); did you mean 'I2C_NUM_MAX'?
93 | if (i2s_num >= I2S_NUM_MAX)
| ^~~~~~~~~~~
| I2C_NUM_MAX

error: 'PERIPHS_IO_MUX_GPIO0_U' undeclared (first
use in this function)
107 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);

error: 'FUNC_GPIO0_CLK_OUT1' undeclared (first use in this function)
107 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);


error: 'PIN_CTRL' undeclared (first use in this function)
108 | WRITE_PERI_REG(PIN_CTRL, 0xFFF0);
| ^~~~~~~~
| ^~~~~~~~~~~~~~~~~~~

viniciusmbs說…
Muito obrigado pelo seu vídeo! Segui os seus passos e consegui iniciar o sistema VoIP, o log mostra: “Sistema VoIP iniciado com sucesso”. Mas agora estou enfrentando um problema: não consigo fazer uma chamada de outra conta SIP (por exemplo, usando o aplicativo Linphone) para a placa ESP. Criei uma conta gratuita no site sip.linphone.org, que me forneceu um domínio público, nome de usuário e um endereço do tipo sip:username@sip.linphone.org. O que eu não tenho certeza é: no sdkconfig ou menuconfig, eu devo preencher com sip:username@sip.linphone.org ou com algo do tipo sip:username:password@sip.linphone.org? Além disso, no código, dentro da estrutura esp_sip_config_t, não sei exatamente quais informações devem ir ali e quais devem ficar no sdkconfig ou menuconfig. Já testei várias combinações, mas o dispositivo ainda não atende as chamadas, e o log fica repetindo o erro: “Evento SIP não tratado: 11”. Eu só consegui chegar até aqui porque assisti ao seu vídeo e segui cada passo. Muito obrigado mesmo! Se você puder dar alguma dica sobre essa parte da configuração (URI, nome de usuário, senha, proxy, etc.), seria ótimo. Sou brasileiro, falo português... mas depois de assistir tantos vídeos seus, acabei te escrevendo em chinês mesmo, hahaha! 😂
viniciusmbs說…
Leaving...
Hard resetting via RTS pin...
[100%] Built target flash
Executing action: monitor
Running idf_monitor in directory /home/vinicius/ESP/esp-adf/examples/get-started/voip
Executing "/home/vinicius/.espressif/python_env/idf4.2_py3.6_env/bin/python /home/vinicius/ESP/esp-idf/tools/idf_monitor.py -p /dev/ttyUSB0 -b 115200 --toolchain-prefix xtensa-esp32-elf- /home/vinicius/ESP/esp-adf/examples/get-started/voip/build/voip_app.elf -m '/home/vinicius/.espressif/python_env/idf4.2_py3.6_env/bin/python' '/home/vinicius/ESP/esp-idf/tools/idf.py'"...
--- idf_monitor on /dev/ttyUSB0 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x1f (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:7456
load:0x40078000,len:14368
load:0x40080400,len:5360
0x40080400: _init at ??:?

entry 0x40080710
I (27) boot: ESP-IDF v4.2.2-dirty 2nd stage bootloader
I (27) boot: compile time 15:34:33
I (27) boot: chip revision: 3
I (31) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (38) qio_mode: Enabling default flash chip QIO
I (43) boot.esp32: SPI Speed : 80MHz
I (48) boot.esp32: SPI Mode : QIO
I (52) boot.esp32: SPI Flash Size : 4MB
I (57) boot: Enabling RNG early entropy source...
I (62) boot: Partition Table:
I (66) boot: ## Label Usage Type ST Offset Length
I (73) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (80) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (88) boot: 2 factory factory app 00 00 00010000 00200000
I (95) boot: 3 flash_tone Unknown data 01 ff 00210000 00080000
I (103) boot: End of partition table
I (107) boot_comm: chip revision: 3, min. application chip revision: 0
I (114) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x21aa4 (137892) map
I (169) esp_image: segment 1: paddr=0x00031acc vaddr=0x3ffb0000 size=0x033c8 ( 13256) load
I (174) esp_image: segment 2: paddr=0x00034e9c vaddr=0x40080000 size=0x0b17c ( 45436) load
0x40080000: _WindowOverflow4 at /home/vinicius/ESP/esp-idf/components/freertos/xtensa/xtensa_vectors.S:1730

viniciusmbs說…
I (194) esp_image: segment 3: paddr=0x00040020 vaddr=0x400d0020 size=0xa009c (655516) map
0x400d0020: _stext at ??:?

I (411) esp_image: segment 4: paddr=0x000e00c4 vaddr=0x4008b17c size=0x0748c ( 29836) load
0x4008b17c: prvGetItemByteBuf at /home/vinicius/ESP/esp-idf/components/esp_ringbuf/ringbuf.c:561 (discriminator 2)

I (433) boot: Loaded app from partition at offset 0x10000
I (433) boot: Disabling RNG early entropy source...
I (434) psram: This chip is ESP32-D0WD
I (438) spiram: Found 64MBit SPI RAM device
I (443) spiram: SPI RAM mode: flash 80m sram 80m
I (448) spiram: PSRAM initialized, cache is in low/high (2-core) mode.
I (455) cpu_start: Pro cpu up.
I (459) cpu_start: Application information:
I (464) cpu_start: Project name: voip_app
I (469) cpu_start: App version: v2.2-dirty
I (474) cpu_start: Compile time: May 29 2025 15:35:28
I (480) cpu_start: ELF file SHA256: 6256b3f01038e756...
I (486) cpu_start: ESP-IDF: v4.2.2-dirty
I (492) cpu_start: Starting app cpu, entry point is 0x40081e88
0x40081e88: call_start_cpu1 at /home/vinicius/ESP/esp-idf/components/esp32/cpu_start.c:287

I (0) cpu_start: App cpu up.
I (1000) spiram: SPI SRAM memory test OK
I (1001) heap_init: Initializing. RAM available for dynamic allocation:
I (1002) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (1007) heap_init: At 3FFB4550 len 0002BAB0 (174 KiB): DRAM
I (1014) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (1020) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (1027) heap_init: At 40092608 len 0000D9F8 (54 KiB): IRAM
I (1033) cpu_start: Pro cpu start user code
I (1038) spiram: Adding pool of 4082K of external SPI memory to heap allocator
I (1058) spi_flash: detected chip: generic
viniciusmbs說…
I (1058) spi_flash: flash io: qio
I (1058) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (1067) spiram: Reserving pool of 18K of internal memory for DMA/internal allocations
I (1077) VOIP_APP: 🚀 Iniciando app_main...
I (1127) wifi:wifi driver task: 3ffc0d88, prio:23, stack:6656, core=0
I (1127) system_api: Base MAC address is not set
I (1127) system_api: read default base MAC address from EFUSE
I (1137) wifi:wifi firmware version: bb6888c
I (1137) wifi:wifi certification version: v7.0
I (1137) wifi:config NVS flash: enabled
I (1147) wifi:config nano formating: disabled
I (1147) wifi:Init data frame dynamic rx buffer num: 128
I (1157) wifi:Init management frame dynamic rx buffer num: 128
I (1157) wifi:Init management short buffer num: 32
I (1167) wifi:Init static tx buffer num: 9
I (1167) wifi:Init tx cache buffer num: 32
I (1167) wifi:Init static rx buffer size: 1600
I (1177) wifi:Init static rx buffer num: 9
I (1177) wifi:Init dynamic rx buffer num: 128
I (1187) wifi_init: rx ba win: 16
I (1187) wifi_init: tcpip mbox: 32
I (1187) wifi_init: udp mbox: 64
I (1197) wifi_init: tcp mbox: 6
I (1197) wifi_init: tcp tx win: 5744
I (1197) wifi_init: tcp rx win: 5744
I (1207) wifi_init: tcp mss: 1440
I (1207) wifi_init: WiFi/LWIP prefer SPIRAM
I (1217) VOIP_APP: Conectando no Wi-Fi SSID: Pandora
I (1227) phy_init: phy_version 4660,0162888,Dec 23 2020
I (1307) wifi:mode : sta (08:a6:f7:b2:26:b4)
I (1307) gpio: GPIO[39]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
E (1307) gpio: gpio_install_isr_service(438): GPIO isr service already installed
I (1607) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
viniciusmbs說…
I (1607) ES8388_DRIVER: init,out:02, in:01
I (1747) gpio: GPIO[5]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1747) gpio: GPIO[13]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1747) gpio: GPIO[18]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1757) gpio: GPIO[19]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1767) gpio: GPIO[23]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1777) gpio: GPIO[36]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1787) AUDIO_HAL: Codec mode is 3, Ctrl:1
I (1887) VOIP_APP: Conectando ao SIP: sip:viniciusesp@sip.linphone.org
I (1887) SIP: esp_sip ver : '1.0.1' Compile date: Oct 27 2020-14:52:00
W (1887) SIP: Invalid scheme
I (1887) VOIP_APP: ⚠️ Evento SIP não tratado: 11
I (1887) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=3
I (1907) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=3
I (1927) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (1927) esp32_audio_kit_v2_3: I2S0, MCLK output by GPIO0
W (1937) I2S: I2S driver already installed
I (1937) esp32_audio_kit_v2_3: I2S0, MCLK output by GPIO0
I (1947) AUDIO_PIPELINE: link el->rb, el:0x3f8141f8, tag:i2s_reader, rb:0x3f814778
I (1957) AUDIO_PIPELINE: link el->rb, el:0x3f8144a4, tag:encoder, rb:0x3f8167b8
I (1957) AUDIO_PIPELINE: link el->rb, el:0x3f8145d4, tag:decoder, rb:0x3f816ff8
I (1967) AUDIO_ELEMENT: [i2s_reader-0x3f8141f8] Element task created
I (1977) AUDIO_THREAD: The encoder task allocate stack on external memory
I (1987) AUDIO_ELEMENT: [encoder-0x3f8144a4] Element task created
I (1987) AUDIO_THREAD: The decoder task allocate stack on external memory
I (1997) AUDIO_ELEMENT: [decoder-0x3f8145d4] Element task created
I (2007) AUDIO_ELEMENT: [i2s_writer-0x3f81437c] Element task created
I (2007) AUDIO_PIPELINE: Func:audio_pipeline_run, Line:359, MEM Total:4290472 Bytes, Inter:269556 Bytes, Dram:213792 Bytes

I (2027) AUDIO_ELEMENT: [i2s_reader] AEL_MSG_CMD_RESUME,state:1
I (2027) I2S_STREAM: AUDIO_STREAM_READER,Rate:44100,ch:2
I (2047) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (2057) AUDIO_ELEMENT: [encoder] AEL_MSG_CMD_RESUME,state:1
I (2057) AUDIO_ELEMENT: [decoder] AEL_MSG_CMD_RESUME,state:1
I (2067) ADF_BIT_STREAM: The element is 0x3f8145d4. The reserve data 2 is 0x0.
I (2077) AUDIO_ELEMENT: [i2s_writer] AEL_MSG_CMD_RESUME,state:1
I (2077) I2S_STREAM: AUDIO_STREAM_WRITER
I (2087) AUDIO_PIPELINE: Pipeline started
I (2087) VOIP_APP: 📞 Sistema VoIP iniciado com sucesso.
W (11897) SIP: CHANGE STATE FROM 0, TO 0, :func: sip_reconnect:312
I (13097) VOIP_APP: ⚠️ Evento SIP não tratado: 11
W (23097) SIP: CHANGE STATE FROM 0, TO 0, :func: sip_reconnect:312
viniciusmbs說…
minha conta no Linphone
person Account information
alternate_email SIP address: sip:viniciusesp@sip.linphone.org

person Username: viniciusesp

dns Domain: sip.linphone.org

lan Proxy/registrar address: sip:sip.linphone.org

settings_ethernet Transport: TLS (recommended), TCP or UDP
漢亞科技說…
Linphone APP is kind of client, so is ESP32. You need a SIP server, and then both clients are registered to SIP server. ESP32 gets an extension number, and Linphone also gets one. You dial extension number to call other side. The account/password/SIP udp tcp tls on Linphone APP are used to register to SIP server.

此網誌的熱門文章

[筆記] ESP32 在 VS Code 開發環境的編譯與除錯

[筆記] Raspberry Pi 樹莓派的軟體開發

初學 ESP32-S3 攝像模組的開發

[筆記] Visual Studio 遠端偵錯的設定步驟

ESP-IDF 在 Visual Studio Code 教學 (不同於 ESP32 Arduino IDE)

[筆記] 整理控制器 STM32 與無線晶片 ESP32 資料